ModelForm, one form, two models

5,325 views
Skip to first unread message

Michel Thadeu Sabchuk

unread,
Sep 10, 2008, 9:59:00 AM9/10/08
to Django users
Hi guys,

What is the best way to work with 2 models on the same forms? Suppose
I have the following case:

class Profile(models.Models):
user = models.ForeignKey(User)
some_data = models.CharField()

How can I add a profile and a user on the same form using ModelForm? I
used to do:

class ProfileForm(models.ModelForm):
class Meta:
model = Profile
first_name = models.CharField()
last_name = models.CharField()
email = models.EmailField()

And then I use form.save(commit=False) and work with the extra data...
Is is the better way? I read about inlineformset_factory but I can't
figure out if it is better for my case.

Any help will be appreciatted!
Best regards,

Joseph Kocherhans

unread,
Sep 10, 2008, 11:48:56 AM9/10/08
to django...@googlegroups.com
On Wed, Sep 10, 2008 at 6:59 AM, Michel Thadeu Sabchuk
<mich...@gmail.com> wrote:
>
> Hi guys,
>
> What is the best way to work with 2 models on the same forms? Suppose
> I have the following case:
>
> class Profile(models.Models):
> user = models.ForeignKey(User)
> some_data = models.CharField()
>
> How can I add a profile and a user on the same form using ModelForm? I
> used to do:
>
> class ProfileForm(models.ModelForm):
> class Meta:
> model = Profile
> first_name = models.CharField()
> last_name = models.CharField()
> email = models.EmailField()

Use 2 separate ModelForms. One for each model. If the 2 models happen
to have overlapping field names, you can use the 'prefix' argument to
the form to avoid name collisions.

One bit to be wary of is calling form.is_valid() in your view. If you
have something like this:

if user_form.is_valid() and profile_form.is_valid():
# save stuff

and user_form.is_valid is False, profile_form.is_valid() won't be
called. I usually write a function called all_valid(list_of_forms)
that calls is_valid() on each form and returns False if any of them
fail.

Joseph

diN0bot

unread,
Sep 22, 2008, 9:57:30 AM9/22/08
to Django users
Seems like Joseph's problem is typical for User/Profile work.

Initially I used the same inheritance model as he does. Working with a
single form in the view and template is a win for code re-use and
simplicity.

I looked into formsets but haven't gotten it to work with multiple
model types. It seems like I should be able to show the User form with
the Profile inlined, right?

My solution is to create a class that generalizes working with
multiple model forms. Or rather, it abstract the multiple form
handling and printing behind a Form interface so that the view and
template don't know the difference. It'd be nice to make more use of
formsets or provided code since I feel like I've reinvented the wheel.

diN0.

On Sep 10, 11:48 am, "Joseph Kocherhans" <jkocherh...@gmail.com>
wrote:

Joseph Kocherhans

unread,
Sep 22, 2008, 11:33:50 AM9/22/08
to django...@googlegroups.com
On Mon, Sep 22, 2008 at 8:57 AM, diN0bot <a.down...@gmail.com> wrote:
>
> Seems like Joseph's problem is typical for User/Profile work.
>
> Initially I used the same inheritance model as he does. Working with a
> single form in the view and template is a win for code re-use and
> simplicity.
>
> I looked into formsets but haven't gotten it to work with multiple
> model types. It seems like I should be able to show the User form with
> the Profile inlined, right?

No. Formsets are designed to work with instances of a single model
type. Inline formsets are closer to what you want, but really, that
adds a lot more complication that just writing 2 forms would. Even if
you *do* use an inline formset, you're still going to have to render
both the form and the formset.

> My solution is to create a class that generalizes working with
> multiple model forms. Or rather, it abstract the multiple form
> handling and printing behind a Form interface so that the view and
> template don't know the difference. It'd be nice to make more use of
> formsets or provided code since I feel like I've reinvented the wheel.

You aren't reinventing the wheel. There isn't code in Django to do
what you're trying to do. If you really feel like you need to write
some sort of wrapper for this, I'd suggest keeping the case you deal
with down to a simple situation: 1 child object with a OneToOneField
or a ForeignKey to a parent object.

Joseph

Reply all
Reply to author
Forward
0 new messages