Proper way to handle multiple forms on one page in Django

后端 未结 10 2157
既然无缘
既然无缘 2020-11-22 09:19

I have a template page expecting two forms. If I just use one form, things are fine as in this typical example:

if request.method == \'POST\':
    form = Au         


        
10条回答
  •  难免孤独
    2020-11-22 09:37

    Django's class based views provide a generic FormView but for all intents and purposes it is designed to only handle one form.

    One way to handle multiple forms with same target action url using Django's generic views is to extend the 'TemplateView' as shown below; I use this approach often enough that I have made it into an Eclipse IDE template.

    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)
    

    The html template is to the following effect:

    ...
    
    
    {% csrf_token %} {{ negotiation_bid_form.as_p }} ...
    ...
    {% csrf_token %} {{ offer_attachment_form.as_p }}
    ...

提交回复
热议问题