一尘不染

使用内联表单集创建模型和相关模型

django

使用内联formset docs中的示例,我能够(使用modelforms)编辑属于特定模型的对象。我一直在尝试使用相同的模式来 使用内联表单集创建新对象,但是一直无法清除我的头来为此目的提供工作视图。

使用与上述链接相同的示例,我将如何创建“作者”模型的新实例及其相关的“书”对象?


阅读 567

收藏
2020-03-27

共2个答案

一尘不染

首先,创建一个Author模型表单。

author_form = AuthorModelForm()

然后创建一个虚拟作者对象:

author = Author()

然后使用伪作者创建内联表单集,如下所示:

formset = BookFormSet(instance=author)  #since author is empty, this formset will just be empty forms

将其发送到模板。数据返回到视图后,你可以创建作者:

author = AuthorModelForm(request.POST)
created_author = author.save()  # in practice make sure it's valid first

现在,将内联表单集与新创建的作者挂钩,然后保存:

formset = BookFormSet(request.POST, instance=created_author)
formset.save()   #again, make sure it's valid first

编辑:

要在新表单上没有复选框,请使用以下模板:

{% for form in formset.forms %}
    <table>
    {% for field in form %}
        <tr><th>{{field.label_tag}}</th><td>{{field}}{{field.errors}}</td></tr>
    {% endfor %}

    {% if form.pk %} {# empty forms do not have a pk #}
         <tr><th>Delete?</th><td>{{field.DELETE}}</td></tr>
    {% endif %}
    </table>
{% endfor %}
2020-03-27
一尘不染

我实际上想对nbv4的解决方案提出一个小的调整:

假设你没有在if-else语句之外创建空的created_author,因此需要将表单集嵌套在author_form.is_valid()中,以避免当author_form无效时(因此没有实例化created_author)运行时错误。

代替:

if request.method == 'POST':
    author_form = AuthorModelForm(request.POST)
    if author_form.is_valid():
        created_author = author_form.save()
        formset = BookFormSet(request.POST, instance=created_author)
        if formset.is_valid():
            formset.save()
            return HttpResponseRedirect(...)
else:
    ...

请执行下列操作:

if request.method == 'POST':
    author_form = AuthorModelForm(request.POST)
    if author_form.is_valid():
        created_author = author_form.save(commit=False)
        formset = BookFormSet(request.POST, instance=created_author)
        if formset.is_valid():
            created_author.save()
            formset.save()
            return HttpResponseRedirect(...)
else:
    ...

此版本避免在book_formset有机会进行验证之前提交created_author。要纠正的用例是,有人用无效的BookFormSet填写了一个有效的AuthorForm并继续重新提交,从而创建了多个Author记录,而这些Book没有与之关联。这似乎适用于我的项目跟踪器应用程序(将“作者”替换为“项目”,将“图书”替换为“角色”)。

2020-03-27