Skip to content

Instantly share code, notes, and snippets.

@teacherSsamko
Forked from badri/cbv_multiple_forms.html
Created March 26, 2020 02:10
Show Gist options
  • Save teacherSsamko/8d079a6a03836147020d0cbe60ea38da to your computer and use it in GitHub Desktop.
Save teacherSsamko/8d079a6a03836147020d0cbe60ea38da to your computer and use it in GitHub Desktop.
Django multiple forms code with sample usage
{% extends "base.html" %}
{% block content %}
<form method="post">{% csrf_token %}
{{ forms.subscription }}
<input type="submit" value="Subscribe">
</form>
<form method="post">{% csrf_token %}
{{ forms.contact }}
<input type="submit" value="Send">
</form>
{% endblock content %}
from django import forms
class MultipleForm(forms.Form):
action = forms.CharField(max_length=60, widget=forms.HiddenInput())
class ContactForm(MultipleForm):
title = forms.CharField(max_length=150)
message = forms.CharField(max_length=200, widget=forms.TextInput)
class SubscriptionForm(MultipleForm):
email = forms.EmailField()
from django.views.generic.base import ContextMixin, TemplateResponseMixin
from django.views.generic.edit import ProcessFormView
class MultiFormMixin(ContextMixin):
form_classes = {}
prefixes = {}
success_urls = {}
initial = {}
prefix = None
success_url = None
def get_form_classes(self):
return self.form_classes
def get_forms(self, form_classes):
return dict([(key, self._create_form(key, class_name)) \
for key, class_name in form_classes.items()])
def get_form_kwargs(self, form_name):
kwargs = {}
kwargs.update({'initial':self.get_initial(form_name)})
kwargs.update({'prefix':self.get_prefix(form_name)})
if self.request.method in ('POST', 'PUT'):
kwargs.update({
'data': self.request.POST,
'files': self.request.FILES,
})
return kwargs
def forms_valid(self, forms, form_name):
form_valid_method = '%s_form_valid' % form_name
if hasattr(self, form_valid_method):
return getattr(self, form_valid_method)(forms[form_name])
else:
return HttpResponseRedirect(self.get_success_url(form_name))
def forms_invalid(self, forms):
return self.render_to_response(self.get_context_data(forms=forms))
def get_initial(self, form_name):
initial_method = 'get_%s_initial' % form_name
if hasattr(self, initial_method):
return getattr(self, initial_method)()
else:
return {'action': form_name}
def get_prefix(self, form_name):
return self.prefixes.get(form_name, self.prefix)
def get_success_url(self, form_name=None):
return self.success_urls.get(form_name, self.success_url)
def _create_form(self, form_name, form_class):
form_kwargs = self.get_form_kwargs(form_name)
form = form_class(**form_kwargs)
return form
class ProcessMultipleFormsView(ProcessFormView):
def get(self, request, *args, **kwargs):
form_classes = self.get_form_classes()
forms = self.get_forms(form_classes)
return self.render_to_response(self.get_context_data(forms=forms))
def post(self, request, *args, **kwargs):
form_classes = self.get_form_classes()
form_name = request.POST.get('action')
return self._process_individual_form(form_name, form_classes)
def _process_individual_form(self, form_name, form_classes):
forms = self.get_forms(form_classes)
form = forms.get(form_name)
if not form:
return HttpResponseForbidden()
elif form.is_valid():
return self.forms_valid(forms, form_name)
else:
return self.forms_invalid(forms)
class BaseMultipleFormsView(MultiFormMixin, ProcessMultipleFormsView):
"""
A base view for displaying several forms.
"""
class MultiFormsView(TemplateResponseMixin, BaseMultipleFormsView):
"""
A view for displaying several forms, and rendering a template response.
"""
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse, reverse_lazy
from .forms import ContactForm, SubscriptionForm
from .multiforms import MultiFormsView
def form_redir(request):
return render(request, 'pages/form_redirect.html')
def multiple_forms(request):
if request.method == 'POST':
contact_form = ContactForm(request.POST)
subscription_form = SubscriptionForm(request.POST)
if contact_form.is_valid() or subscription_form.is_valid():
# Do the needful
return HttpResponseRedirect(reverse('form-redirect') )
else:
contact_form = ContactForm()
subscription_form = SubscriptionForm()
return render(request, 'pages/multiple_forms.html', {
'contact_form': contact_form,
'subscription_form': subscription_form,
})
class MultipleFormsDemoView(MultiFormsView):
template_name = "pages/cbv_multiple_forms.html"
form_classes = {'contact': ContactForm,
'subscription': SubscriptionForm,
}
success_urls = {
'contact': reverse_lazy('form-redirect'),
'subscription': reverse_lazy('form-redirect'),
}
def contact_form_valid(self, form):
title = form.cleaned_data.get('title')
form_name = form.cleaned_data.get('action')
print(title)
return HttpResponseRedirect(self.get_success_url(form_name))
def subscription_form_valid(self, form):
email = form.cleaned_data.get('email')
form_name = form.cleaned_data.get('action')
print(email)
return HttpResponseRedirect(self.get_success_url(form_name))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment