组合表单和 inline_formset 的编辑视图

Editing view for combined form and inline_formset

我一直在尝试创建一个编辑视图,允许我使用基于文档 here

的内联表单集来管理父模型和子模型

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

目前代码导致“没有 return 一个 HttpResponse 对象。它 returned 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

URL


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

提到的错误是因为你在 else 块中写了这个 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)

这样做:

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

        context = {

            }

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

可能是您的表单或表单集无效,您没有使用 else 语句来处理。

所以在你的 views.py:

    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:
            # either your form or formset is invalid, so this code will render it again.
            context = {
              'shoppinglist' : shoppinglist,
              'listform': form, 
              'formset': formset,
            }

            return render(request, 'edit_list_with_items.html', context)
    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)

或者你可以这样简化它:

    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)
    # notice the indentation
    context = {
        'shoppinglist' : shoppinglist,
        'listform': form, 
        'formset': formset,
    }

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