views:

264

answers:

3

I have 2 objects, both from different Model classes, and want to show a form containing some fields from each one. How can I do this?

A: 

I've never tried this but you could have two ModelForm classes defined in your code and then make a new plain Form class that in its __init__ created a copy of each ModelForm and copied the fields into itself.

Something like:

class DualForm(forms.Form):
    def __init__(self, *args, **kwargs):
        model1 = Model1Form(**kwargs)
        model2 = Model2Form(**kwargs)

        for f in model1.fields:
            self.fields[f] = model1.fields[f]

        for f in model2.fields:
            self.fields[f] = model2.fields[f]

class Model1Form(forms.ModelForm):
    ... your model form...

class Model2Form(forms.ModelForm):
    ... your other model form...

I can't see why it wouldn't work.

Just make sure you pass data arguments through to the ModelForms and trap and bubble exceptions out... I'm also not sure what would happen if you have conflicting field names. That could be troublesome...

Oli
And these are exactly the kind of error-prone contortions people go to when they assume everything has to be squeezed into one Form object... just use two!
Carl Meyer
+3  A: 

The way I do it is by creating two ModelForm classes that use the fields Meta attribute to specify which subset of fields to use to display in the form. I display both forms in the template, and handle them in the view.

ayaz
This is the right answer. Django Form/ModelForm objects do not equal HTML forms, they're just collections of fields; you wrap them in the <form> tag yourself. Don't go into contortions squeezing everything into one Form/ModelForm, use as many as you need and put them all inside a single HTML form.
Carl Meyer
A: 

Just create 2 separate forms, the problem with with the approach of the guy above is that you would lose .save(). Forms are really meant to represent 1 single set of data, the data for each of yours models is really a separate set of data. This is why forms doesn't include the tag when the render.

Alex Gaynor