Django Forms: One View, Multiple Forms
A method for using multiple forms in one Django view


Published on by nick

Tags: django, forms, prg

I recently encountered a problem that I couldn't figure out. I'm building an app that has a feed where users can post and comment on these posts. The basic idea is simple, but when I went to add the comment form, I realized that I needed multiple forms on one page. This in itself is not difficult... You simply add multiple form elements to your HTML:

<form id="form1" method="post">
    <input id="field1" type="test">
    <input type="submit">
</form>
<form id="form2" method="post">
    <input id="field2" type="test">
    <input type="submit">
</form>

The tricky part is that in Django, by default, when you create a form instance, it renders an id that is either the same as the field name or something like this: id_field_name.

In general, this is fine. But if you create multiple forms on one page, each might have a duplicate id. To get around this, you need to specify auto_id=False when you instantiate the form:

form = self.form_class(auto_id=False)

But if you go ahead and try this with multiple forms, it still won't work. With one form, this will simply generate a form without an id. To make it so Django plays nice with coexisting forms in one view, you also need to use the form prefix parameter.

post_form = self.post_form_class(prefix='post_form', auto_id=False)
comment_form = self.comment_form_class(prefix='comment_form', auto_id=False)

Putting this all together, you might have a view that looks like this:

post_model = Post
comment_model = Comment

post_form_class = AddPostForm
comment_form_class = AddCommentForm

. . .

@method_decorator(login_required)
def get(self, request):

    post_form = self.post_form_class(prefix='post', auto_id=False)
    comment_form = self.comment_form_class(prefix='comment', auto_id=False)

    . . .

For completeness, one of my form classes might look something like this (notice the widget attributes for Bootstrap):

class AddCommentForm(ModelForm):
    class Meta:
        model = Comment
        fields = ['message']

    message = forms.CharField(
        widget=forms.Textarea(
            attrs={
                'class': 'form-control comment-input'
                'name': 'message',
                'placeholder': 'Comment away...'
            }
        ),
        required=False,
    )

When you read this, you might be thinking, "this seems simple." And you'd be right! But before I knew any of this, it was driving me crazy. Hopefully this will save someone out there a bit of time when you are building your cool Django apps.

Comments

Comments powered by Disqus

 Blog Search

  Popular Tags

django, ubuntu, mod_wsgi, apache, authentication, python, tls, linux, forms, ssl, virtualenv, dell, uwsgi, bash, nginx, raid, customer-service, centurylink, ux, software-companies, rais, form, centos, password, certificates, tinymce, mdadm, dual-boot, file-server, virtualhost, gluster, IT, blog, get, networking, piplight, distributed-file-system, big companies, bitnami, cygwin, windows, samba, scripting, pygments, post, programming-language, ui, lampstack, outsourcing, isp, security, usabillity, provision, php, shared-hosting, netflix, git, flatpages, syntax-highlighting, virtualbox, hg, redirect, usability, prg, acls, change-password, complex, view tags...

 Questions/Comments?

Drop me a line... [email protected]
Follow me on Twitter... @nicorellius
Share on Facebook...