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. """