Django 内联表单集自定义验证一次仅验证单个表单集

发布于 2024-10-10 14:00:13 字数 2634 浏览 5 评论 0原文

我正在使用 Django,并且有一个带有两个附加内联表单集的表单。我想验证每个表单集是否至少包含一个填充表单。我已经编写了这样的代码,但它一次只适用于每个表单集。如果我提交的表单没有填充任何表单集表单,则只有第一个表单显示验证错误。如果我随后填充第一个表单集表单,并将第二个表单留空,则第二个表单会出错。

如果两种形式都无效,我希望错误出现在两种形式上。

这些表单只是标准的 ModelForm 实例。这是我的观点:

class RequiredBaseInlineFormSet(BaseInlineFormSet):
    def clean(self):
        self.validate_unique()
        if any(self.errors):
            return
        if not self.forms[0].has_changed():
            raise forms.ValidationError("At least one %s is required" % self.model._meta.verbose_name)

def create(request):
    profile_form = ProfileForm(request.POST or None)
    EmailFormSet = inlineformset_factory(Profile, Email, formset=RequiredBaseInlineFormSet, max_num=5, extra=5, can_delete=False)
    email_formset = EmailFormSet(request.POST or None)
    PhoneFormSet = inlineformset_factory(Profile, Phone, formset=RequiredBaseInlineFormSet, max_num=5, extra=5, can_delete=False)
    phone_formset = PhoneFormSet(request.POST or None)
    if profile_form.is_valid() and email_formset.is_valid() and phone_formset.is_valid():
        profile = profile_form.save()
        emails = email_formset.save(commit=False)
        for email in emails:
            email.profile = profile
            email.save()
        phones = phone_formset.save(commit=False)
        for phone in phones:
            phone.profile = profile
            phone.save()
        messages.add_message(request, messages.INFO, 'Profile successfully saved')
    return render_to_response(
        'add.html', {
            'profile_form': profile_form,
            'email_formset': email_formset,
            'phone_formset': phone_formset
        }, context_instance = RequestContext(request)
    )

这是我的模板表单,以防它有用:

<form action="" method="post" accept-charset="utf-8">
    {{ email_formset.management_form }}
    {{ phone_formset.management_form }}
    {{ profile_form|as_uni_form }}
    <div class="formset-group" id="email_formset">
        {{ email_formset.non_form_errors }}
        {% for email_form in email_formset.forms %}
            <div class='form'>
                {{ email_form|as_uni_form }}
            </div>
        {% endfor %}
    </div>
    <div class="formset-group" id="phone_formset">
        {{ phone_formset.non_form_errors }}
        {% for phone_form in phone_formset.forms %}
            <div class='form'>
                {{ phone_form|as_uni_form }}
            </div>
        {% endfor %}
    </div>
    <input type="submit" value="Save Profile" id="submit">
</form>

I'm using Django and have a form with two additional inline formsets. I want to validate that each formset contains at least one populated form. I've written code such that this works but it only works for each formset at a time. If I submit the form without any formset forms populated, only the first one shows a validation error. If I then populate the first formset form, and leave the second one blank, the second one errors.

I want errors to appear on both forms if both are not valid.

The forms are just standard ModelForm instances. Here's my view:

class RequiredBaseInlineFormSet(BaseInlineFormSet):
    def clean(self):
        self.validate_unique()
        if any(self.errors):
            return
        if not self.forms[0].has_changed():
            raise forms.ValidationError("At least one %s is required" % self.model._meta.verbose_name)

def create(request):
    profile_form = ProfileForm(request.POST or None)
    EmailFormSet = inlineformset_factory(Profile, Email, formset=RequiredBaseInlineFormSet, max_num=5, extra=5, can_delete=False)
    email_formset = EmailFormSet(request.POST or None)
    PhoneFormSet = inlineformset_factory(Profile, Phone, formset=RequiredBaseInlineFormSet, max_num=5, extra=5, can_delete=False)
    phone_formset = PhoneFormSet(request.POST or None)
    if profile_form.is_valid() and email_formset.is_valid() and phone_formset.is_valid():
        profile = profile_form.save()
        emails = email_formset.save(commit=False)
        for email in emails:
            email.profile = profile
            email.save()
        phones = phone_formset.save(commit=False)
        for phone in phones:
            phone.profile = profile
            phone.save()
        messages.add_message(request, messages.INFO, 'Profile successfully saved')
    return render_to_response(
        'add.html', {
            'profile_form': profile_form,
            'email_formset': email_formset,
            'phone_formset': phone_formset
        }, context_instance = RequestContext(request)
    )

And here's my template's form, incase it's useful:

<form action="" method="post" accept-charset="utf-8">
    {{ email_formset.management_form }}
    {{ phone_formset.management_form }}
    {{ profile_form|as_uni_form }}
    <div class="formset-group" id="email_formset">
        {{ email_formset.non_form_errors }}
        {% for email_form in email_formset.forms %}
            <div class='form'>
                {{ email_form|as_uni_form }}
            </div>
        {% endfor %}
    </div>
    <div class="formset-group" id="phone_formset">
        {{ phone_formset.non_form_errors }}
        {% for phone_form in phone_formset.forms %}
            <div class='form'>
                {{ phone_form|as_uni_form }}
            </div>
        {% endfor %}
    </div>
    <input type="submit" value="Save Profile" id="submit">
</form>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凹づ凸ル 2024-10-17 14:00:13

为您希望进行验证的每个表单调用 is_valid() 函数。在您的示例中,您执行 if a.is_valid 和 b.is_valid anc c.is_valid... 如果 a 为 false,则 b 和 c 将永远不会被调用。尝试一些不同的东西,比如:

alpha=a.is_valid()
beta=b.is_valid()
gamma=c.is_valid()

if alpha and beta and gamma: 
  do stuff

call the is_valid() function for each form that you want validation to occur on. In your example you do if a.is_valid and b.is_valid anc c.is_valid... If a is false, b and c will never get called. Try something different, like:

alpha=a.is_valid()
beta=b.is_valid()
gamma=c.is_valid()

if alpha and beta and gamma: 
  do stuff
琉璃梦幻 2024-10-17 14:00:13

我遇到了类似的问题,问题是由于 Django 处理额外表单字段的方式,额外的表单没有得到验证。看一下:Django Formset.is_valid() 对于额外表单失败

I had a similar issue and the problem was that extra forms were not being validated due to how Django handles extra form fields. Take a look: Django Formset.is_valid() failing for extra forms

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文