Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: Can class-based views accept two forms at a time?

Tags:

If I have two forms:

class ContactForm(forms.Form):     name = forms.CharField()     message = forms.CharField(widget=forms.Textarea)  class SocialForm(forms.Form):     name = forms.CharField()     message = forms.CharField(widget=forms.Textarea) 

and wanted to use a class based view, and send both forms to the template, is that even possible?

class TestView(FormView):     template_name = 'contact.html'     form_class = ContactForm 

It seems the FormView can only accept one form at a time. In function based view though I can easily send two forms to my template and retrieve the content of both within the request.POST back.

variables = {'contact_form':contact_form, 'social_form':social_form } return render(request, 'discussion.html', variables) 

Is this a limitation of using class based view (generic views)?

Many Thanks

like image 753
Houman Avatar asked Mar 19 '13 11:03

Houman


People also ask

How do class-based views work in Django?

A view is a callable which takes a request and returns a response. This can be more than just a function, and Django provides an example of some classes which can be used as views. These allow you to structure your views and reuse code by harnessing inheritance and mixins.

How submit multiple forms Django?

Create a Django project and an app, I named the project "multipleFormHandle" and the app as "formhandlingapp". Do some basic stuff like including app in settings.py INSTALLED_APPS and include app's url in project's url. Now create forms.py in app and a "templates" folder in the app directory. Add home.

How to use decorators in Django class-based views?

To decorate every instance of a class-based view, you need to decorate the class definition itself. To do this you apply the decorator to the dispatch() method of the class. The decorators will process a request in the order they are passed to the decorator.

Why we use class-based views in Django?

The most significant advantage of the class-based view is inheritance. In the class-based view, you can inherit another class, and it can be modified for the different use cases. It helps you in following the DRY principle. You won't have to write the same code over and over in your boilerplate.


1 Answers

Here's a scaleable solution. My starting point was this gist,

https://gist.github.com/michelts/1029336

i've enhanced that solution so that multiple forms can be displayed, but either all or an individual can be submitted

https://gist.github.com/jamesbrobb/748c47f46b9bd224b07f

and this is an example usage

class SignupLoginView(MultiFormsView):     template_name = 'public/my_login_signup_template.html'     form_classes = {'login': LoginForm,                     'signup': SignupForm}     success_url = 'my/success/url'      def get_login_initial(self):         return {'email':'[email protected]'}      def get_signup_initial(self):         return {'email':'[email protected]'}      def get_context_data(self, **kwargs):         context = super(SignupLoginView, self).get_context_data(**kwargs)         context.update({"some_context_value": 'blah blah blah',                         "some_other_context_value": 'blah'})         return context      def login_form_valid(self, form):         return form.login(self.request, redirect_url=self.get_success_url())      def signup_form_valid(self, form):         user = form.save(self.request)         return form.signup(self.request, user, self.get_success_url()) 

and the template looks like this

<form class="login" method="POST" action="{% url 'my_view' %}">     {% csrf_token %}     {{ forms.login.as_p }}      <button name='action' value='login' type="submit">Sign in</button> </form>  <form class="signup" method="POST" action="{% url 'my_view' %}">     {% csrf_token %}     {{ forms.signup.as_p }}      <button name='action' value='signup' type="submit">Sign up</button> </form> 

An important thing to note on the template are the submit buttons. They have to have their 'name' attribute set to 'action' and their 'value' attribute must match the name given to the form in the 'form_classes' dict. This is used to determine which individual form has been submitted.

like image 122
james Avatar answered Feb 14 '23 05:02

james