Jest to problem, który miał do mnie podczas pracy nad projektem Django. Chodzi o walidację formularza.

W Django, gdy masz złożony formularz, możesz zadzwonić is_valid() na odpowiednim obiekcie formularza, aby wywołać walidację i zwrócić wartość boolowską. Zazwyczaj masz taki kod w swoim widoku Funkcje:

if form.is_valid():
    # code to save the form data

is_valid() Nie tylko weryfikuje dane formularza, ale także dodaje komunikaty o błędach do obiektu formularzowego, który potem może być wyświetlany użytkownikowi.

Na jednej stronie używam dwóch formularzy razem, a także chcesz, aby dane były zapisywane tylko wtedy, gdy obie formy zawierają prawidłowe dane. Oznacza to, że muszę zadzwonić do is_valid () na obu formularzach przed wykonaniem kodu, aby zapisać dane. Najbardziej oczywisty sposób:

if form1.is_valid() and form2.is_valid():
    # ...

Nie będzie działać z powodu ocenę zwarciowej operatorów logicznych. Jeśli formularz1 jest nieprawidłowy, forma2 nie zostanie oceniony, a jego komunikaty o błędach brakuje.

To tylko przykład. O ile wiem, nie ma chciwej alternatywy dla and / or jak w innych językach (tj. Smalltalk). Mogę sobie wyobrazić, że problem występujący w różnych okolicznościach (a nie tylko w Pythonie). Rozwiązania, o których mogłem wymyślić, są wszelkiego rodzaju niezdarne (zagnieżdżone ifs, przypisując wartości zwrotne do zmiennych lokalnych i używając ich w instrukcji IF). Chciałbym poznać drogę Pythonic, aby rozwiązać tego rodzaju problemy.

Z góry dziękuję!

24
j0ker 5 wrzesień 2012, 16:29

3 odpowiedzi

Najlepsza odpowiedź

Co powiesz na coś takiego:

if all([form1.is_valid(), form2.is_valid()]):
   ...

W ogólnym przypadku można zastosować rozumienie listy, aby wyniki są obliczane z przodu (w przeciwieństwie do wyrażenia generatora, które są powszechnie używane w tym kontekście). na przykład.:

if all([ form.is_valid() for form in (form1,form2) ])  

Spowoduje to ładnie skalowanie do dowolnej liczby warunków ... Jedynym połówą jest to, że wszystkie muszą być połączone "and", w przeciwieństwie do if foo and bar or baz: ....

(W przypadku niezgodnego obwodu or można użyć any zamiast all).

36
mgilson 5 wrzesień 2012, 13:11

Możesz po prostu użyć operatora binarnego &, co zrobi logiczne logiczne nie krótkotrwałe i i na bools.

if form1.is_valid() & form2.is_valid():
   ...
23
sloth 5 wrzesień 2012, 12:43

Możesz użyć Clever Infix Hack do definiowania własnych operatorów boolowskich
Aand = Infix (Lambda X, Y: Bool (X) i Bool (Y))
1 | Aand | 2 powróci true zamiast 1

0
Avinash 19 grudzień 2019, 18:30