5

次のように定義された数量フィールドを持つ複数のフォームを含む 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'

4

1 に答える 1

1

docsによると、empty_valuea のデフォルトは空の文字列であり、その値は強制されません。TypedChoiceField

時々空の値を取得している可能性が非常に高く、TypeError をスローしている文字列は空の文字列です。試す:

quantity = TypedChoiceField(coerce=int, required=False, empty_value=0)
于 2013-03-15T19:14:01.890 に答える