Django Model Formsets with Inline Formsets: 在模型表单中使用内联表单集处理表单集

2023-04-07 00:00:00 模型 表单 内联

Django Model Formsets allow you to process multiple models at once through a single form. However, there may be cases where you need to process a set of related models through the same form. This is where Inline Formsets come into play.

An Inline Formset is a formset for a model that has a foreign key to another model. For example, let's say we have a simple model structure where every Author can publish multiple Books:

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)

Now, we want to be able to add/edit authors and their books through a single form. We can achieve this using Model Formsets and Inline Formsets.

First, let's define a Model Form for both Author and Book models:

from django import forms
from .models import Author, Book

class AuthorForm(forms.ModelForm):
    class Meta:
        model = Author
        fields = ['name']

class BookForm(forms.ModelForm):
    class Meta:
        model = Book
        fields = ['title']

Next, let's define an Inline Formset for Book model:

from django.forms import inlineformset_factory

BookFormSet = inlineformset_factory(Author, Book, form=BookForm, extra=1)

Here, we are using inlineformset_factory to create an Inline Formset for Book model, with Author model as the parent model. The form parameter specifies the BookForm we defined earlier, and extra parameter specifies the number of extra Book forms to be displayed.

Finally, in our view function, we can use both AuthorForm and BookFormSet to process the form data:

from django.shortcuts import render
from .models import Author, Book
from .forms import AuthorForm, BookForm, BookFormSet

def add_author(request):
    if request.method == 'POST':
        author_form = AuthorForm(request.POST)
        book_formset = BookFormSet(request.POST)

        if author_form.is_valid() and book_formset.is_valid():
            author = author_form.save() # save Author model
            book_formset.instance = author # set author as the instance for each Book form
            book_formset.save() # save Book models

            return HttpResponseRedirect('/success/')

    else:
        author_form = AuthorForm()
        book_formset = BookFormSet()

    return render(request, 'add_author.html', {'author_form': author_form, 'book_formset': book_formset})

Here, we first check if the request method is POST. If it is, we validate both AuthorForm and BookFormSet. If both are valid, we first save the Author model using author_form.save(), then assign the author instance to each Book form using book_formset.instance = author, and finally save all Book models using book_formset.save().

If the request method is not POST, we simply instantiate both forms and pass them to the template.

In the template, we can render both forms using {{ author_form.as_p }} and {{ book_formset.as_table }}.

Note: If you want to use 'pidancode.com' or '皮蛋编程' as an example string, simply replace any occurrence of "Author" with "编程" and any occurrence of "Book" with "网站".

相关文章