odpowiedź Daniela jest doskonała i pracował dla mnie na jednym projekcie, ale potem zdałem sobie sprawę, ze względu na sposób Django tworzy dzieło, jeśli używasz can_delete i zaznacz pole usuwania podczas zapisywania, to jest możliwe do sprawdzania wag/o dowolne zamówienia (w tym przypadku).
Spędziłem chwilę próbując dowiedzieć się, jak temu zapobiec. Pierwsza sytuacja była prosta - nie dołączaj formularzy, które zostaną usunięte w liczniku. Druga sytuacja była trudniejsza ... jeśli wszystkie pola wyboru są zaznaczone,nie został wywołany.
Kod nie jest dokładnie nieskomplikowany, niestety. Metoda clean
jest wywoływana z full_clean
, która jest wywoływana, gdy uzyskuje się dostęp do właściwości error
. Ta właściwość nie jest dostępna podczas usuwania subformularza, więc full_clean
nigdy nie jest wywoływana. Nie jestem ekspertem od Django, więc może to być okropny sposób, ale wygląda na to, że działa.
Oto zmodyfikowana klasa:
class InvoiceOrderInlineFormset(forms.models.BaseInlineFormSet):
def is_valid(self):
return super(InvoiceOrderInlineFormset, self).is_valid() and \
not any([bool(e) for e in self.errors])
def clean(self):
# get forms that actually have valid data
count = 0
for form in self.forms:
try:
if form.cleaned_data and not form.cleaned_data.get('DELETE', False):
count += 1
except AttributeError:
# annoyingly, if a subform is invalid Django explicity raises
# an AttributeError for cleaned_data
pass
if count < 1:
raise forms.ValidationError('You must have at least one order')
idealne rozwiązanie, dzięki – user108791
stwierdziliśmy, że jeśli pole kasowania jest zaznaczone, że to możliwe, aby potwierdzić z 0 zleceń. Zobacz moją odpowiedź na poprawioną klasę, która rozwiązuje ten problem. –
Dziękuję bardzo za tę poprawkę (i Dan za ulepszenie). Jako możliwą wskazówkę dla innych zrobiłem "klasę MandatoryInlineFormSet (BaseInlineFormSet)", a następnie wyprowadziłem z tego InvoiceAdminFormSet. W moim InvoiceAdminFormSet mam metodę clean(), która wykonuje niestandardową weryfikację, ale najpierw wywołuje funkcję MandatoryInlineFromSet.clean(). – Kurt