- October 2, 2014
- Not specified
- 1 (after 1 ratings)
This is a simple example of feeding multiple Forms into a single Form via its constructor method, to work with a single FormView and reap the benefits of Django's awesome Form validation system. It's a Form class that defines (or takes via an argument to its constructor) parent Forms (that can, for instance, be ModelForms, to take advantage of the automatic Field generation) and takes its fields from there.
An advanced user won't be impressed by this, so excuse if this snippet is out of place, but a rather inexperienced user such as myself might find it interesting and make him willing to explore Django's internals a bit more.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
class ActualForm(forms.Form): """ This form's fields are the sum of the fields defined by its parent forms. By creating this form dynamically I'm able to take advantage of the ModelForms functionality of automatically setting the Model's fields while still ending up with a form that comprises multiple models. The Parent forms are specified in the :attr: parent_forms or received in the constructor as :arg: parent_forms """ parent_forms = [SomeForm1, SomeForm2] def __init__(self, parent_forms=, *args, **kwargs): super(ActualForm, self).__init__(*args, **kwargs) # If the class was instantiated with a list of parent Forms as # an argument, use said list. Else look for a hard-coded attribute. # This line is hilarious. parent_forms = parent_forms if parent_forms else self.parent_forms # Make a list of form fields. The list comprehension makes a # nested list that gets flattened by itertools' chain form_values = list(itertools.chain( *[form().fields.iteritems() for form in parent_forms] )) # Add the values of the parent forms to the actual form for k, v in form_values: self.fields[k] = v # In Views: class ActualFormView(FormView): """ Use the Class Based View as always, but make sure to set form_class to be the dynamic Form. """ form_class = ActualForm def form_valid(self, form): # Create objects. Do stuff. return super(ActualFormView, self).form_valid(form)