Friday, April 2, 2010

Multiple Django forms in the same view

When you want to handle multiple Django forms within the same view you need some extra coding as opposed to having a single form. This is needed because:

  • You want to identify which form has been submitted to your view.
  • And you don't want to confuse fields from one form with fields from another.
So let's start with identifying the form from your view. You'll first need to add some information to your template to distinguish between the two forms. This can be easily done by giving a unique name to each submit buttons. For the rest of this post we will assume that we have two forms: A and B.

<fieldset>
    <legend>Form A</legend>
    <form method="post">
        {{ A_form.as_p }}
        <input name="A" type="submit" value="Submit" />
    </form>
</fieldset>

<fieldset>
    <legend>Form B</legend>
    <form method="post">
        {{ B_form.as_p }}
        <input name="B" type="submit" value="Submit" />
    </form>
</fieldset>

Now that you uniquely identified both forms you can add some logic to your view to get to know which submit button as been pressed.


if 'A' in request.POST:
    # A form processing
elif 'B' in request.POST:
    # B_form processing

What happens above is that you search the submitted POST data dictionary for the name you gave to your submit buttons. That's all there is to it.

However if for some reason fields in the different forms you present to your users have the same names then you need to add a couple more lines of code to distinguish between them. From the django documentation you can borrow the strategy in using more than one formset in a view. The idea is to prefix each field name with a form identifier. I choose to use the same token for the prefix and for the submit button name.

The end result would be something like this:

class AForm(forms.Form):
    fieldname = forms.CharField(max_length=25)

class BForm(forms.Form):
    fieldname = forms.CharField(max_length=25)

if 'A' in request.POST:
    A_form = AForm(request.POST, prefix='A')
    B_form = BForm(prefix='B')
    # A form processing
elif 'B' in request.POST:
    B_form = BForm(request.POST, prefix='B')
    A_form = AForm(prefix='A')
    # B_form processing


8 comments:

  1. Yeah. Great idea. I know. But what about the form checks? Where and how would you display the error messages if they don't fill it correctly? In the form itself? Above all forms?

    I know it's not a code question but I'm more interrested in the functional aspects of the idea and I was wondering what is your opinion on the matter?

    ReplyDelete
  2. Hello Mia,

    My preference as a user is to have the fields that contain errors highlighted with a clear explanation just below or next to the field.

    On a multiple forms webpage I would just do the same... as long as the overall design allows it.

    ReplyDelete
  3. I'm thankful about your explanation, this article works so good for my problem.

    ReplyDelete
  4. What if one wants to use one submit button? Is there any way to do that ?

    ReplyDelete
  5. This comment has been removed by the author.

    ReplyDelete
  6. Мне нравится ваш блог, я прочитал этот блог, пожалуйста, обновите больше контента на python. И мне нравится BDPU

    ReplyDelete