次のように定義された数量フィールドを持つ複数のフォームを含む FormSet を使用しています。
quantity = TypedChoiceField(coerce=int, required=False)
少なくとも 1 つの数量が 0 より大きいかどうかを知りたいので、フォームセットのクリーンで次のように記述します。
def clean(self):
if sum([form.cleaned_data['quantity'] for form in self.forms]) == 0:
raise forms.ValidationError(_('No products selected'))
したがって、通常、これは機能し、form.cleaned_data['quantity'] は int (coerce=int で設定) です。しかし、時々 (このフォームの 2000 リクエストごとに 1 回など)、次のような例外が発生します。
TypeError: unsupported operand type(s) for +: 'int' and 'str'
その行で、これは form.cleaned_data['quantity'] が文字列であることを意味し、sum() は文字列の合計を好まないため、例外をスローします。Python コンソールを起動して次のように入力することで、これを自分でテストできます。
>>> sum([u'1', u'2'])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'unicode'
>>>
だから私の質問は、なぜこれが起こるのですか? また、なぜこれがめったに起こらないのですか?django のドキュメントによると、 TypedChoiceField の強制は clean() が呼び出される前に行われることが保証されているため、これは発生しないはずです。
このバグは再現するのが非常に難しいため、修正するのが難しいため、このような問題が発生したことがある方がいらっしゃることを願っています。
これは python 2.6 と django 1.3.1 にあります。
前もって感謝します!
編集 したがって、スタックトレースは次のとおりです。
File "****/handlers/products.py" in process
429. if formset.is_valid():
File "/usr/local/lib/python2.6/dist-packages/django/forms/formsets.py" in is_valid
263. err = self.errors
File "/usr/local/lib/python2.6/dist-packages/django/forms/formsets.py" in _get_errors
241. self.full_clean()
File "/usr/local/lib/python2.6/dist-packages/django/forms/formsets.py" in full_clean
287. self.clean()
File "****/handlers/products.py" in clean
217. if sum([form.cleaned_data['quantity'] for form in self.forms]) == 0:
例外タイプ: 例外値での TypeError /****/url
: + のサポートされていないオペランド タイプ: 'int' および 'str'