首页 > 解决方案 > 组合表单和 inline_formset 的编辑视图

问题描述

我一直在尝试创建一个编辑视图,允许我使用基于此处文档的内联表单集来管理父模型和子模型

据我所知,表单集没有验证。我确实尝试过更改它,而不是验证整个表单集,而是遍历表单集中的每个单独的表单并单独验证它们。这确实允许我将项目添加到表单集中但不能删除它们。

目前,代码导致“没有返回 HttpResponse 对象。它返回 None ”值错误,因为重定向位于 If valid 语句中,因此如果这不导致 true 则没有其他重定向可以依靠.

楷模


class Shoppinglist(models.Model):
    name = models.CharField(max_length=50)
    description = models.TextField(max_length=2000)
    created = models.DateField(auto_now_add=True) 
    created_by = models.ForeignKey(User, related_name='lists', on_delete=models.CASCADE)
    last_updated = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name

class Item(models.Model):
    name = models.CharField(max_length=80, unique=True)
    amount = models.IntegerField(default=1)
    shoppinglist = models.ForeignKey(Shoppinglist, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

网址


urlpatterns = [
   url(r'^shoppinglists/(?P<pk>\d+)/edit/$', views.shoppinglist_edit, name='shoppinglist_edit'),
]

看法


def shoppinglist_edit(request, pk):

    try:
        shoppinglist = Shoppinglist.objects.get(pk=pk)
    except ShoppingList.DoesNotExist:
        raise Http404
    
    ItemInlineFormset = inlineformset_factory(Shoppinglist, Item, extra=1, fields=('name', 'amount'))

    if request.method == "POST":
        form = ShoppinglistForm(request.POST, instance=shoppinglist)
        formset = ItemInlineFormset(request.POST, instance=shoppinglist)

        if formset.is_valid() and form.is_valid():
            form.save()
            formset.save()
            return redirect('packlist_list', pk=pk)    

    else:
        form = ShoppinglistForm(instance=shoppinglist)
        formset = ItemInlineFormset(instance=shoppinglist)

        context = {
            'shoppinglist' : shoppinglist,
            'listform': form, 
            'formset': formset,
            }

        return render(request, 'edit_list_with_items.html', context)

模板


{% block content %}
<form method="post">
    {% csrf_token %}

    <label>List Name</label>
    {{ listform.name }}
    {% if listform.first_name.errors %}
        {% for error in listform.first_name.errors %}
            {{ error|escape }}
        {% endfor %}
    {% endif %}

    <label>Description</label>
    {{ listform.description }}
    {% if listform.description.errors %}
        {% for error in listform.description.errors %}
            {{ error|escape }}
        {% endfor %}
    {% endif %}

    {{ formset.management_form }}

    {% for form in formset %}
        <div class="item-formset">
            {{ form.amount }}
            {% if form.amount.errors %}
                {% for error in form.amount.errors %}
                    {{ error|escape }}
                {% endfor %}
            {% endif %}

            {{ form.name }}
            {% if form.name.errors %}
                {% for error in form.name.errors %}
                    {{ error|escape }}
                {% endfor %}
            {% endif %}
        </div>
    {% endfor %}

    {% if formset.non_form_errors %}
        {% for error in formset.non_form_errors %}
            {{ error|escape }}
        {% endfor %}
    {% endif %}

    <div class="row spacer">       
            <button type="submit" class="btn btn-block btn-primary">Create</button>
    </div>
</form>
{% endblock %}

{% block extra_js %}
<script>
  $('.item-formset').formset({
      addText: 'add item',
      deleteText: 'remove'
  });
</script>
{% endblock %}


请注意我在模板中使用这个 jquery 插件。

https://github.com/elo80ka/django-dynamic-formset

标签: pythondjangodjango-formsformset

解决方案


提到错误是因为你return render(request, 'edit_list_with_items.html', context)在 else 块中写了这个。

而不是这个:

else:
        form = ShoppinglistForm(instance=shoppinglist)
        formset = ItemInlineFormset(instance=shoppinglist)

        context = {
            '
            }

        return render(request, 'edit_list_with_items.html', context)

做这个:

else:
        form = ShoppinglistForm(instance=shoppinglist)
        formset = ItemInlineFormset(instance=shoppinglist)

        context = {

            }

return render(request, 'edit_list_with_items.html', context)

推荐阅读