如何在Django中获得内联formset的反转?

时间:2013-07-07 19:19:04

标签: django django-forms

请参阅下面the documentation of Django中的示例:

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)

class Book(models.Model):
    author = models.ForeignKey(Author)
    title = models.CharField(max_length=100)
     

如果要创建允许编辑书籍的表单集   属于特定作者,您可以这样做:

>>> from django.forms.models import inlineformset_factory
>>> BookFormSet = inlineformset_factory(Author, Book)
>>> author = Author.objects.get(name=u'Mike Royko')
>>> formset = BookFormSet(instance=author)

这是与作者对书籍的一对多关系,并为单个作者提供了一种编辑书籍的简便方法。

现在我想做相反的事情:一个用于编辑/创建作者的表单,其中包含用于编辑/创建的内联图书集。我怎么做?我真的更喜欢使用ModelForms和来实现这一点,而无需创建其中一个模型的实例。

例如:

添加作者表格

  • 作者姓名:[________]
  • 书籍:
    • 标题:[________]
    • 标题:[________]
    • 标题:[________]
    • (添加更多)
  • [save]

注意:此时我不需要任何作者实例。

我可能错过了一些简单的东西,我在这里的文档上花了太多时间。欢迎提供一些帮助!

1 个答案:

答案 0 :(得分:4)

我会在同一视图中使用ModelForm AuthorModelFormset Book来执行此操作。像这样:

in forms.py:
AuthorForm = modelform_factory(Author)
BooksFormset = modelformset_factory(Book, extra=3, fields=('title',))

in views.py:
if request.method == POST:
    author_form = AuthorForm(request.POST)
    books_formset = BooksFormset(request.POST)
    if author_form.is_valid() and books_formset.is_valid():
        author = author_form.save()
        new_books = books_formset.save(commit=False)
        for new_book in new_books:
            new_book.author = author
            new_book.save()
        # not actually needed with these models, but a good habit to include nonetheless
        books_formset.save_m2m()
        return redirect('some-success-view')
else:
    author_form = AuthorForm()
    books_formset = BooksFormset(queryset=Book.objects.none()) # or give a different initial queryset if you want some preselected choice
extra_context = {'author_form': author_form, 'books_formset': books_formset}
return render(request, 'some_template', extra_context)

内联表单集基本上为您执行作者实例和书籍实例之间的绑定。在内部,内联formset使用基于您提供的父模型实例的查询集 - 我认为在instance=None代码路径中传入get并且如果作者表单未在{ {1}}可行,但我从未测试过。

另外,我并没有在这里处理'添加更多'行为 - 管理员从Jquery插件中获取该行为,这应该很容易复制到您自己的表单上。