Is it possible to have multiple models included in a single
ModelForm in django? I am trying to create a profile edit form. So I need to include some fields from the User model and the UserProfile model. Currently I am using 2 forms like this
class UserEditForm(ModelForm): class Meta: model = User fields = ("first_name", "last_name") class UserProfileForm(ModelForm): class Meta: model = UserProfile fields = ("middle_name", "home_phone", "work_phone", "cell_phone")
Is there a way to consolidate these into one form or do I just need to create a form and handle the db loading and saving myself?
You can just show both forms in the template inside of one
<form> html element. Then just process the forms separately in the view. You'll still be able to use
form.save() and not have to process db loading and saving yourself.
In this case you shouldn't need it, but if you're going to be using forms with the same field names, look into the
prefix kwarg for django forms. (I answered a question about it here).
You can try to use this pieces of code:
class CombinedFormBase(forms.Form): form_classes =  def __init__(self, *args, **kwargs): super(CombinedFormBase, self).__init__(*args, **kwargs) for f in self.form_classes: name = f.__name__.lower() setattr(self, name, f(*args, **kwargs)) form = getattr(self, name) self.fields.update(form.fields) self.initial.update(form.initial) def is_valid(self): isValid = True for f in self.form_classes: name = f.__name__.lower() form = getattr(self, name) if not form.is_valid(): isValid = False # is_valid will trigger clean method # so it should be called after all other forms is_valid are called # otherwise clean_data will be empty if not super(CombinedFormBase, self).is_valid() : isValid = False for f in self.form_classes: name = f.__name__.lower() form = getattr(self, name) self.errors.update(form.errors) return isValid def clean(self): cleaned_data = super(CombinedFormBase, self).clean() for f in self.form_classes: name = f.__name__.lower() form = getattr(self, name) cleaned_data.update(form.cleaned_data) return cleaned_data
class ConsumerRegistrationForm(CombinedFormBase): form_classes = [RegistrationForm, ConsumerProfileForm] class RegisterView(FormView): template_name = "register.html" form_class = ConsumerRegistrationForm def form_valid(self, form): # some actions... return redirect(self.get_success_url())