首页 > 解决方案 > Django 错误 NoReverseMatch 因为它缺少一个 pk

问题描述

所以目前我在一个带有这样的 url 链接的页面上

urls.py:

path('key/<int:pk>', views.KeyDetailView.as_view(), name='roomkey-detail'),

视图.py:

class KeyDetailView(generic.DetailView):
    model = RoomKey

这列出了可用于特定房间借用的钥匙列表。然后,当我尝试前往下一页时,我可以在哪里提出借用该房间的其中一个钥匙的请求,这是负责呈现房间钥匙请求页面的 url 和视图

urls.py:

path('key/<int:pk>/request', views.KeyRequestCreate.as_view(), name='roomkey-request')

视图.py:

class KeyRequestCreate(CreateView):
    model = KeyRequest
    fields = ['roomkey', 'requester', 'borrower', 'request_comments']
    template_name = 'catalog/roomkey_request_form.html'

该页面上有一个按钮,链接到如下所示的条款和协议页面

roomkey_request_form.html:

<a href="{% url 'key-agreement' roomkey.pk %}">terms and conditions</a>

urls.py:

path('key/<int:pk>/request/agreement', views.KeyAgreement, name='key-agreement'),

视图.py:

def KeyAgreement(request):

return render(
    request,
    'catalog/roomkey_agreement.html',
)

但是,当尝试单击该请求按钮以请求密钥时,django 会引发错误

NoReverseMatch at /catalog/key/2/request
Reverse for 'key-agreement' with arguments '('',)' not found. 1 pattern(s) 
tried: ['catalog\\/key\\/(?P<pk>[0-9]+)\\/request\\/agreement$']

我在条款和协议上有一个按钮,可以返回请求页面,看起来像这样

<button href="{% url 'roomkey-request' roomkey.pk %}" >Return to request</button>

这会以正确的pk返回请求页面吗?我想我只是对 url 如何处理 pk 以及它如何传递感到困惑。我认为这与 keyagreement 无法从详细信息页面中获取该 pk 的某些事情有关,有人可以向我解释我做错了什么或指向一些可以帮助我了解 url 如何在视图之间传递 pk 的资源?我对 django 很陌生,所以提前感谢您的帮助!

标签: pythondjango

解决方案


如果要roomkey.pkroomkey_request_form.html模板中使用,则需要添加roomkey到模板上下文中。您可以在get_context_data方法中执行此操作。

由于您已经从 URL 中获得了 roomkey pk,因此您可以将其从fields. 然后在保存前roomkeyform_valid方法中设置。

class KeyRequestCreate(CreateView):
    model = KeyRequest
    fields = ['requester', 'borrower', 'request_comments']
    template_name = 'catalog/roomkey_request_form.html'

    def get_context_data(self, **kwargs):
        context = super(KeyRequestCreate, self).get_context_data(**kwargs)
        context['roomkey'] = get_object_or_404(RoomKey, pk=pk)

    def form_valid(self, form):
        form.instance.roomkey = get_object_or_404(RoomKey, pk=pk)
        return super(KeyRequestCreate, self).get_form(form)

如果您想roomkey在协议视图中使用,您还必须对其进行一些更改。

首先,您需要添加pk到函数签名中,因为您<int:pk>在其 URL 模式中有。

然后,您需要包含roomkey在模板上下文中。

from django.shortcuts import get_object_or_404

def key_agreement(request, pk):
    roomkey = get_object_or_404(roomkey, pk=pk)
    return render(
        request,
        'catalog/roomkey_agreement.html',
        {'roomkey': roomkey}
    )

请注意,我已重命名视图函数key_agreement以匹配推荐的样式。您还需要更新 URL 模式。

path('key/<int:pk>/request/agreement', views.KeyAgreement, name='key-agreement'),

推荐阅读