Django Model Forms with Inline Formsets and Many-to-Many Relationships: 在模型表单中处理内联表单集和多对多关系

2023-04-07 00:00:00 django model forms

Django 提供了 ModelForm 来简化模型表单的创建,能够根据模型自动生成表单字段。但是,当涉及到内联表单集和多对多关系时,我们需要使用到 inlineformset_factory

inlineformset_factory 可以帮助我们在模型表单中处理内联表单集,它接收一个父模型和一个子模型作为参数,返回一个可以用于表单的表单集。多对多关系需要使用 ModelMultipleChoiceField 作为表单字段,它将对应的模型对象转换为表单中的多选框。

接下来,我们通过一个示例演示如何在模型表单中处理内联表单集和多对多关系。假设有以下两个模型:

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=50)
    email = models.EmailField()

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)

我们需要为 Book 模型创建一个模型表单,并添加一组内联表单集用于添加作者,以及一个多对多关系用于选择作者。

首先,我们需要导入以下模块:

from django.forms import inlineformset_factory, ModelForm, ModelMultipleChoiceField

然后,我们可以定义一个子模型表单,用于添加作者:

AuthorFormSet = inlineformset_factory(Book, Book.authors.through, fields=('author',), extra=1)

接着,我们可以定义一个模型表单,并在其中添加一个多对多关系表单字段和一个内联表单集字段:

class BookForm(ModelForm):
    authors = ModelMultipleChoiceField(queryset=Author.objects.all(), required=False)

    class Meta:
        model = Book
        fields = ('title', 'authors')

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.instance:
            self.fields['authors'].initial = self.instance.authors.all()

        self.author_formset = AuthorFormSet(instance=self.instance)

    def save(self, commit=True):
        instance = super().save(commit=commit)
        if commit:
            self.author_formset.save()
        return instance

我们在表单中添加了一个名为 authors 的多对多关系表单字段,并在 __init__() 方法中初始化了一个 AuthorFormSet 对象作为内联表单集字段。在 save() 方法中,我们将保存 Book 对象的负责提交,然后保存所有子表单数据。

最后,我们可以在视图函数中处理表单提交:

from django.shortcuts import render, redirect
from .models import Book
from .forms import BookForm

def add_book(request):
    if request.method == 'POST':
        form = BookForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('book_list')
    else:
        form = BookForm()
    return render(request, 'add_book.html', {'form': form})

以上就是在 Django 模型表单中处理内联表单集和多对多关系的示例代码。如果您需要在代码演示中使用字符串作为范例,请根据需要将“pidancode.com”或“皮蛋编程”替换为字符串。

相关文章