1

Say I have two basic classes, one with a ManyToMany relationship to the other:

class Foo(models.Model):
    abc = models.TextField()
    test = models.ManyToManyField(Bar)

class Bar(models.Model):
    zyx = models.TextField()

And then I create a Django form for Foo:

class FooForm(forms.ModelForm):
    class Meta:
        model = Foo
        fields = ["abc", "test"]

This will create a form with a TextArea for me to input the value of the new Foo's abc variable, as well as a listbox to link it to one or more Bar objects. What I would like to do for this particular form, is instead of the listbox for the Bar objects, be able to create one (and only one) new Bar at the same time (i.e., display a second TextArea for the value of Bar's zyx) and then link that new Bar to the new Foo. The ManyToMany relationship comes in later on in editing, but at creation, I want exactly one Bar tied to the one new Foo.

Is it possible to do this all at once by POSTing the form, or am I going to have to use some javascript and AJAX to actually create the Bar first, get its new ID, and link the new Foo to that?

okm
  • 23,575
  • 5
  • 83
  • 90
Joseph
  • 12,678
  • 19
  • 76
  • 115

1 Answers1

1

It is possible, but I'm not sure a ModelForm would do that for you.


However, you can easily do it on your own:

Set up the forms for the user to fill-in:

  • Create a form to let the user input abc (that could be a ModelForm)
  • Create a formset out of a form that let the user enter an arbitrary number of zyx to create related Bar instances. (Again, formset of ModelForm is OK)

When processing the POST data, do the following:

  1. Validate the form and the formset are valid
  2. Insert the new instances
  3. Add your new Bar instances to your new Foo's Bar ManyToMany relationship

Small tip: remember that ModelForm.save returns the instance!

Community
  • 1
  • 1
Thomas Orozco
  • 53,284
  • 11
  • 113
  • 116
  • Assuming I would only ever want one new Bar at the creation of the new Foo, this should be simpler and not require the formset, correct? – Joseph Dec 05 '12 at 14:48
  • Since my `Bar` only has one field, I think the easiest thing to do following your guide is just to create an extra field under the `Foo` ModelForm ( `zyx = forms.CharField(widget=forms.Textarea)` ) and then use that to create and link a new `Bar` in the view handling the POST. I appreciate the help! – Joseph Dec 05 '12 at 15:13
  • @Joseph It does, but if you need to future proof your code, using `ModelForm`'s can sometimes be very useful, as it will save you time to just add a new field to the `ModelForm`! : ) – Thomas Orozco Dec 05 '12 at 15:16
  • You're right, and I'm already realizing this as I need to do something similar for a third class, so I will go with ModelForm. Question- how are the forms differentiated in the view from request.POST? Is Django just going to know to put the right data in the right forms? – Joseph Dec 05 '12 at 15:47
  • @Joseph If the form have non-conflicting fields, yes. Otherwise, [use the `prefix` kwarg](http://stackoverflow.com/questions/2374224/django-working-with-multiple-forms) when you instantiate the form! – Thomas Orozco Dec 05 '12 at 16:14