【问题标题】:NoReverseMatch error for combined form and model_formset组合表单和模型表单集的 NoReverseMatch 错误
【发布时间】:2019-06-05 08:12:17
【问题描述】:

我一直在尝试按照tutorial 中的用例三创建一个使用 model_formsets 组合父模型和子模型的 for。

型号

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+)/$', views.shoppinglist_list, name='shoppinglist_list'),
   url(r'^shoppinglists/new/$', views.create_shoppinglist_with_items, name='shoppinglist_new'),
]

表格

class ShoppingListForm(forms.ModelForm):
    description = forms.CharField(
        widget=forms.Textarea(
            attrs={'rows': 5, 'placeholder': 'Tell us about your list?'}
        ), 
        max_length=4000,
        help_text='The max length of the text is 4000 characters.'
    )

    class Meta:
        model = Shoppinglist
        fields = ['name', 'description']

ItemFormset = modelformset_factory(
    Item,
    fields=('name', 'amount'),
    extra=1,
    widgets={
        'name': forms.TextInput(
            attrs={
                'class': 'form-control',
                'placeholder': 'Enter Item Name here'
            }
        )
    },
    can_delete=True
    
)

查看

@login_required
def create_shoppinglist_with_items(request):
    template_name = 'list_with_items.html'
    if request.method == 'GET':
        listform = ShoppinglistForm(request.GET or None)
        formset = ItemFormset(queryset=Item.objects.none())
    elif request.method == 'POST':
        listform = ShoppinglistForm(request.POST)
        formset = ItemFormset(request.POST)
        if listform.is_valid() and formset.is_valid():
            shoppinglist = listform.save(commit=False)
            shoppinglist.created_by = request.user
            shoppinglist = listform.save()
            for form in formset:               
                item = form.save(commit=False)
                item.shoppinglist = shoppinglist
                item.save()
            return redirect('shoppinglist_list', pk=shoppinglist.pk)
    return render(request, template_name, {
        'listform': listform,
        'formset': formset,
    })

模板

{% 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 %}

我已经修改了代码,以便将用户带到新创建的父模型,但是当我转到该页面时,我收到了 NoReverseMatch 错误。

Reverse for 'shoppinglist_list' with arguments '('',)' not found. 1 pattern(s) tried: ['shoppinglists/(?P<pk>\\d+)/$']

【问题讨论】:

  • 此错误与表单或表单集无关。它不是来自这段代码。显示模板。
  • @DanielRoseman 我现在已经添加了模板。

标签: python django python-3.x django-2.1


【解决方案1】:

来自docs

如果您在 commit=False 的情况下调用 save(),那么它将返回一个尚未保存到数据库的对象。在这种情况下,您可以在生成的模型实例上调用 save()。

在您执行shoppinglist = listform.save(commit=False) 之后,您在shoppinglist 变量中获得了模型实例。

所以你应该使用shoppinglist = shoppinglist.save() 而不是shoppinglist = listform.save()

保存模型实例后,您可以访问shoppinglist.pk

【讨论】:

  • 恐怕这还没有解决问题。我认为 Daniel Roseman 是对的,这与模板有关,因此我将其添加到原始问题中。
【解决方案2】:

只是为了关闭这张票,模板中有一个错字,我已经更正了,这导致了这个问题。所以上面的代码现在可以工作了。

【讨论】:

    猜你喜欢
    • 2015-09-02
    • 2017-07-17
    • 1970-01-01
    • 1970-01-01
    • 2018-12-03
    • 2021-02-20
    • 2012-08-13
    • 2010-10-28
    • 1970-01-01
    相关资源
    最近更新 更多