在 Django 的一个页面上使用多个表单

Posted

技术标签:

【中文标题】在 Django 的一个页面上使用多个表单【英文标题】:Using multiple forms on a page in Django 【发布时间】:2011-08-16 23:22:39 【问题描述】:

如何在 Django 中每页使用多个表单?

【问题讨论】:

请提供更多信息,否则我们无法为您提供帮助。 Proper way to handle multiple forms on one page in Django 的可能重复项 【参考方案1】:

请参阅以下之前提出(并已回答)的问题:

Django: multiple models in one template using forms

Proper way to handle multiple forms on one page in Django.

根据您的实际要求,这是我最喜欢在同一页面上处理不同模型的方式:

if request.POST():
    a_valid = formA.is_valid()
    b_valid = formB.is_valid()
    c_valid = formC.is_valid()
    # we do this since 'and' short circuits and we want to check to whole page for form errors
    if a_valid and b_valid and c_valid:
        a = formA.save()
        b = formB.save(commit=False)
        c = formC.save(commit=False)
        b.foreignkeytoA = a
        b.save()
        c.foreignkeytoB = b
        c.save()

【讨论】:

感谢您的解释。就我而言,我有两个模型(父子模型)并在一个模板中呈现两个表单。当我提交表单时, parent.is_valid() 返回 true 但 child.is_valid() 为 false 并且错误显示“此字段不能为空”,其中“此字段”是我在子项中的外键模型字段型号【参考方案2】:

从您提出问题的日期来看,我假设您正在使用基于类的视图,下面是从我的其他答案中复制的:Proper way to handle multiple forms on one page in Django

class NegotiationGroupMultifacetedView(TemplateView):
    ### TemplateResponseMixin
    template_name = 'offers/offer_detail.html'

    ### ContextMixin 
    def get_context_data(self, **kwargs):
        """ Adds extra content to our template """
        context = super(NegotiationGroupDetailView, self).get_context_data(**kwargs)

        ...

        context['negotiation_bid_form'] = NegotiationBidForm(
            prefix='NegotiationBidForm', 
            ...
            # Multiple 'submit' button paths should be handled in form's .save()/clean()
            data = self.request.POST if bool(set(['NegotiationBidForm-submit-counter-bid',
                                              'NegotiationBidForm-submit-approve-bid',
                                              'NegotiationBidForm-submit-decline-further-bids']).intersection(
                                                    self.request.POST)) else None,
            )
        context['offer_attachment_form'] = NegotiationAttachmentForm(
            prefix='NegotiationAttachment', 
            ...
            data = self.request.POST if 'NegotiationAttachment-submit' in self.request.POST else None,
            files = self.request.FILES if 'NegotiationAttachment-submit' in self.request.POST else None
            )
        context['offer_contact_form'] = NegotiationContactForm()
        return context

    ### NegotiationGroupDetailView 
    def post(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)

        if context['negotiation_bid_form'].is_valid():
            instance = context['negotiation_bid_form'].save()
            messages.success(request, 'Your offer bid #0 has been submitted.'.format(instance.pk))
        elif context['offer_attachment_form'].is_valid():
            instance = context['offer_attachment_form'].save()
            messages.success(request, 'Your offer attachment #0 has been submitted.'.format(instance.pk))
                # advise of any errors

        else 
            messages.error('Error(s) encountered during form processing, please review below and re-submit')

        return self.render_to_response(context)

html模板的作用如下:

...

<form id='offer_negotiation_form' class="content-form" action='./' enctype="multipart/form-data" method="post" accept-charset="utf-8">
    % csrf_token %
     negotiation_bid_form.as_p 
    ...
    <input type="submit" name=" negotiation_bid_form.prefix -submit-counter-bid" 
    title="Submit a counter bid"
    value="Counter Bid" />
</form>

...

<form id='offer-attachment-form' class="content-form" action='./' enctype="multipart/form-data" method="post" accept-charset="utf-8">
    % csrf_token %
     offer_attachment_form.as_p 

    <input name=" offer_attachment_form.prefix -submit" type="submit" value="Submit" />
</form>

...

【讨论】:

这个:data = self.request.POST if 'NegotiationAttachment-submit' in self.request.POST else None!!!! @zeraien ? - 你能澄清一下 当在同一页面上有多个表单时,向提交按钮添加键/值可以让我在视图处理代码中区分不同的表单。所以在我的例子中,我创建了一个小方法,我为每个表单调用...def _get_post(request, prefix): return request.POST if '%s-submit' % prefix in request.POST else None,每个表单只是调用它来获取 POST 数据:password_form = PasswordChangeForm(user=request.user, data=_get_post(request, 'password'), prefix='password') 那行给了我这样做的灵感;-)跨度>

以上是关于在 Django 的一个页面上使用多个表单的主要内容,如果未能解决你的问题,请参考以下文章

使用 Django 在一个页面上登录和注册表单

django:csrf_token 用于单个页面上的多个表单和 ajax 请求

一个页面上的多个表单

在一个页面中使用带有多个 django 表单的 jQuery datepicker

Django:使用相同的视图在两个单独的页面上处理相同的表单

如何在 Django 中访问表单提交按钮的值?