Welcome to django-multiform’s documentation!¶
Django-multiform is a library that allows you to wrap several forms into one object with a form-like API.
It’s compatible with django 1.4 and 1.5.
A lot of care has been put into replicating the same API as Form so that a MultiForm can be used anywhere a regular Form would.
The library consists of two classes: MultiForm
and MultiModelForm
.
MultiForm¶
Wraps up several Form
into one object, which allows you for example
to reuse several existing forms in a generic FormView
.
# forms.py
from django import forms
from multiform import MultiForm
class FooForm(forms.Form):
foo = forms.CharField()
class BarForm(forms.Form):
bar = forms.CharField()
class FooBarForm(MultiForm):
base_forms = [
('foo', FooForm),
('bar', BarForm),
]
# views.py
from django.views import generic
from .forms import FooBarForm
class FooBarView(generic.FormView):
form_class = FooBarForm
def form_valid(self, form):
form.cleaned_data['foo'] # {'foo': ...}
form.cleaned_data['bar'] # {'bar': ...}
return super(FooBarView, self).form_valid(form)
MultiModelForm¶
As the name hints, it wraps several ModelForm
instances into one object.
It’s quite similar to MultiForm
, but it adds a save
method and it can
handle the dispatching of the instance
attribute that you usually
pass to a ModelForm
.
It’s useful for creating related model instances in one step with a generic CreateView for example.
# models.py
from django.db import models
class Person(models.Model):
eye_color = models.CharField(max_length=50)
user = models.OneToOneField(auth.get_user_model())
# forms.py
from django.contrib.auth.forms import UserCreationForm
from .models import Person
from multiform import MultiModelForm
class PersonUserForm(MultiModelForm):
base_forms = [
('person', PersonForm),
('user', UserCreationForm),
]
def dispatch_init_instance(self, name, instance):
if name == 'person':
return instance
return super(PersonUserForm, self).dispatch_init_instance(name, instance)
def save(self, commit=True):
"""Save both forms and attach the user to the person."""
instances = super(PersonUserForm, self).save(commit=False)
instances['person'].user = instances['user']
if commit:
for instance in instances.values():
instance.save()
return instances
Dispatching Parameters¶
In the event that you want to pass different parameters to some of the wrapped forms, you have two options (that can be used independently):
- Implement a
dispatch_init_$arg
method on your subclass. This method will be called when builting the keyword arguments passed to a wrapped form’s constructor. This method is passed two arguments: the name of the wrapped form being built, and the original value of the $arg keyword argument. - Pass a
$name__$arg=foo
keyword argument to the MultiForm’s constructor. This will make it so that the wrapped form with the name of$name
will be passed the$arg=foo
keyword argument. Note that in case of conflicts, this method has priority over the first one.
Any keyword argument passed to a Multiform’s contructor that’s not part of
the Form’s signature and that’s not of the form $name__*
will be passed to
all wrapped forms.