I am trying to find a simple way to create a form that allows the editing of two models with foreign key relationship simultaneously.
After some research, it seems that Inline formsets come very close to what I want to do.
The django documentation offers this example:
from django.db import models class Author(models.Model): name = models.CharField(max_length=100) class Book(models.Model): author = models.ForeignKey(Author, on_delete=models.CASCADE) title = models.CharField(max_length=100)
And then,
>>> from django.forms import inlineformset_factory >>> BookFormSet = inlineformset_factory(Author, Book, fields=('title',)) >>> author = Author.objects.get(name='Mike Royko') >>> formset = BookFormSet(instance=author)
Let’s suppose Author
has a second field, city
. Can I use the fields
argument to add a city to the form?
If inline formsets are not the way to go, is there another way that generates this joint form?
After some more research, I found django model Form. Include fields from related models from 2009 which hints that inline form sets might not be the way to go.
I would be very much interested if there’s a default solution with a different factory.
Advertisement
Answer
Well, this is a bit different from the linked post because there the relationship is a OneToOne
and not a ForeignKey
.
There is no django factory (at least that I know of) to do what you want automatically. You can try the following instead:
Create a
ModelForm
for the depended table (Book
in this case):class BookForm(forms.ModelForm): class Meta: model = Book fields = ['name', 'city', 'other_field', ...]
Create an
inline_formset
for the depended table:BookFormSet = inlineformset_factory(Author, Book, form=BookForm)
Use the formset in your view:
def my_view(request): if request.method == 'POST': formset = BookFormSet(request.POST, instance=request.user) if formset.is_valid(): ... formset.save() else: formset = BookFormSet(instance=request.user) return render_to_response("template.html", {"formset": formset})
OR in a class based view: django class-based views with inline model-form or formset
Finally in the template (this part needs a bit of fumbling to get it right, but this is a general idea):
<form action="." method="post"> {% csrf_token %} {{ formset }} {{ formset.management_form }} <input type="submit" value="Submit"> </form>