Django - 内联表单集验证

use*_*ser 3 python django

我正在尝试验证我的内联表单集成本值,以确保它总计为 100。表单集返回 5 次,因此应该添加 foreach 值,直到达到 100。如果大于或小于该值,则会显示错误并且不允许用户点击创建按钮。我正在尝试验证所有组合的表单而不是每个表单值。

模型.py

class EstimatedBudgetForm(forms.ModelForm):
def clean(self):
    # get forms that actually have valid data
    count = 0
    for percentage in self.cost:
        try:
            if percentage.cleaned_data:
                count += percentage
        except AttributeError:
            # annoyingly, if a subform is invalid Django explicity raises
            # an AttributeError for cleaned_data
            pass
    if count != 100:
        raise forms.ValidationError('Percentage must equal 100%')
Run Code Online (Sandbox Code Playgroud)

视图.py

EstimatedBudgetChildFormset = inlineformset_factory(
  Project, EstimatedBudget, fields=('project', 'item', 'cost', 'time'), can_delete=False, form=EstimatedBudgetForm, extra=5, widgets={'item': forms.Select(attrs={'disabled': True})},
)
Run Code Online (Sandbox Code Playgroud)

Abd*_*kat 5

要对表单集执行验证,应该重写clean表单集(而不是表单)的方法。对于内联表单集,您需要继承BaseInlineFormSet并使用它(有关更多信息,请参阅Overriding clean() on a ModelFormSet [Django docs]):

from django.forms import BaseInlineFormSet


class MyInlineFormset(BaseInlineFormSet):
    def clean(self):
        super().clean()
        count = 0
        for form in self.forms:
            if not form.errors: # No need for a try-except, just check if the form doesn't have errors
                count += form.cleaned_data['cost']
        if count != 100: # This condition might not work if you are dealing with floating point numbers
            raise forms.ValidationError('Percentage must equal 100%')
Run Code Online (Sandbox Code Playgroud)

接下来,在制作表单集时,指定formsetkwarg 而不是form

EstimatedBudgetChildFormset = inlineformset_factory(
  Project, EstimatedBudget, fields=('project', 'item', 'cost', 'time'), can_delete=False, formset=MyInlineFormset, extra=5, widgets={'item': forms.Select(attrs={'disabled': True})},
)
Run Code Online (Sandbox Code Playgroud)