2013-03-15 26 views
5

Używam formset, który zawiera kilka form, które każdy ma równe ilości, która jest zdefiniowana następująco:formset użyciu TypedChoiceField nie zmuszany do int raz ~ 2000 wnioski

quantity = TypedChoiceField(coerce=int, required=False) 

Chcę wiedzieć, czy w najmniej jeden ilość> 0, więc w moim formset na czysty, to piszę:

def clean(self): 
    if sum([form.cleaned_data['quantity'] for form in self.forms]) == 0: 
     raise forms.ValidationError(_('No products selected')) 

tak, to po prostu działa normalnie, a form.cleaned_data [ „ilość”] jest int (jak określono przez przymusić = int) . Ale raz na jakiś czas (jak raz na 2000 wnioski o tej formie), otrzymuję wyjątek, który mówi mi:

TypeError: unsupported operand type(s) for +: 'int' and 'str' 

na tej linii, co oznacza form.cleaned_data [ „ilość”] jest ciągiem , a sum() nie lubi sumowania ciągów, więc rzuca wyjątek. Możesz to sprawdzić samodzielnie, uruchamiając konsolę Pythona i wpisując:

>>> 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' 
>>> 

Moje pytanie brzmi: dlaczego tak się dzieje? A także dlaczego tak rzadko się to zdarza? Dokumentacja django mówi mi, że wymuszanie na maszynie TypedChoiceField jest gwarantowane przed wywołaniem metody clean(), więc nie powinno to mieć miejsca.

Błąd jest trudny do naprawienia, ponieważ jest trudny do odtworzenia, więc mam nadzieję, że jeden z was miał problem podobny do tego.

To jest na python 2.6 i django 1.3.1.

Z góry dziękuję!

EDIT Więc tutaj jest StackTrace:

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: 

Typ wyjątku: TypeError na /****/url Exception Wartość: nieobsługiwany typ operandu (y) +: 'int' i 'str'

+0

Problem ten brzmi dość zlokalizowane, ale zacząłbym łapanie specyficzny wyjątek w kodzie żywo i zalogować zmiennych forma mieszkańców wokół tego punktu przerwania, a potem tylko czekać na to, aby powtórzy więc trzeba co najmniej coś do debugowania. Btw Sentry to fajne narzędzie do automatyzacji tego, goodluck –

Odpowiedz

1

Domyślnym empty_value dla TypedChoiceField jest pusty łańcuch, zgodnie z the docs, a ta wartość nie jest wymuszana.

Myślę, że jest bardzo prawdopodobne, że otrzymujesz pustą wartość przy okazji, a ciąg, który rzuca twój TypeError to pusty ciąg. Spróbuj:

quantity = TypedChoiceField(coerce=int, required=False, empty_value=0) 
+0

To dziwne, ponieważ mam ślad Exception w Sentry, który również zapisał zawartość Post, a wartość ilości zawierała u'1 '. To oczywiście nie jest pusta wartość. – jaapz

+0

Czy mogę rzucić okiem na ten ślad? – Hamms

+0

Dodałem stacktrace do posta :) – jaapz