django.core.exceptions.ImproperlyConfigured:无法使用视图名称“用户详细信息”解析超链接关系的 URL

Posted

技术标签:

【中文标题】django.core.exceptions.ImproperlyConfigured:无法使用视图名称“用户详细信息”解析超链接关系的 URL【英文标题】:django.core.exceptions.ImproperlyConfigured: Could not resolve URL for hyperlinked relationship using view name "user-detail" 【发布时间】:2017-02-25 15:49:13 【问题描述】:

TL;DR:我收到此错误,不知道为什么:

。您可能未能在 API 中包含相关模型,或者该字段的“lookup_field”属性配置不正确。

我正在浏览django-rest-framework tutorial,目前正处于将基于函数的视图 (FBV) 切换到基于类、mixin 和基于泛型的视图(分别为 CBV、MBV、GBV)的地步。切换到GBV后,当我去测试我的API时,我收到了这个错误AssertionError: Expected view SnippetDetail to be called with a URL keyword argument named "pk". Fix your URL conf, or set the '.lookup_field' attribute on the view correctly.。我做了一些研究,发现lookup_fieldneeds to be set to the in the urlpatterns。目前,我的 urls.py 看起来像这样:

from django.conf.urls import url, include
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views

# API endpoints
urlpatterns = format_suffix_patterns([
    url(r'^$', views.api_root),
    url(r'^snippets/$',
        views.SnippetList.as_view(),
        name='snippet-list'),
    url(r'^snippets/(?P<id>[0-9]+)/$',
        views.SnippetDetail.as_view(),
        name='snippet-detail'),
    url(r'^users/$',
        views.UserList.as_view(),
        name='user-list'),
    url(r'^users/(?P<id>[0-9]+)/$',
        views.UserDetail.as_view(),
        name='user-detail')
])

# Login and logout views for the browsable API
urlpatterns += [
    url(r'^auth/', include('rest_framework.urls',
                           namespace='rest_framework')),
]

我的 views.py 看起来像这样:

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer, UserSerializer
from snippets.permissions import IsOwnerOrReadOnly

from rest_framework import generics
from rest_framework import permissions
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse

from django.contrib.auth.models import User


@api_view(['GET'])
def api_root(request, format=None):
    return Response(
        'users': reverse('user-list', request=request, format=format),
        'snippets': reverse('snippet-list', request=request, format=format)
    )


class UserList(generics.ListAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer


class UserDetail(generics.RetrieveAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer


class SnippetList(generics.ListCreateAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly, )

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)


class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly, )

当我在 UserDetail 和 SnippetDetail 中添加 lookup_field = 'id' 时,异常会自行解决。 (耶!)。但是,当我访问http://127.0.0.1/users/1/ 时,ImproperlyConfigured: Could not resolve URL for hyperlinked relationship using view name "user-detail". You may have failed to include the related model in your API, or incorrectly configured the 'lookup_field' attribute on this field. 被抛出。但是,当我检查控制台时,还有第二个异常:

django.urls.exceptions.NoReverseMatch:“用户详细信息”的反向 未找到参数 '()' 和关键字参数 ''pk': 1'。 2 尝试的模式:['users/(?P[0-9]+)\.(?P[a-z0-9]+)/?$', '用户/(?P[0-9]+)/$']

在处理上述异常的过程中,又发生了一个异常:

django.core.exceptions.ImproperlyConfigured:无法解析 URL 使用视图名称“用户详细信息”的超链接关系。你可能有 未能在您的 API 中包含相关模型,或不正确 在该字段上配置了“lookup_field”属性。

我觉得有趣的是,第一个异常的 kwargs 是 'pk': 1,而不是 'id':1。在聊天的帮助下,有人给我指了this的一条信息:

请注意,在使用超链接 API 时,如果您需要使用自定义值,则需要确保 API 视图和序列化程序类都设置了查找字段。

这很有用,因为User 序列化程序扩展了HyperlinkedModelSerializer

from rest_framework import serializers

from django.contrib.auth.models import User

from snippets.models import Snippet

class UserSerializer(serializers.HyperlinkedModelSerializer):
    snippets = serializers.HyperlinkedRelatedField(many=True, view_name='snippet-detail', read_only=True)

    class Meta:
        model = User
        fields = ('url', 'id', 'username', 'snippets')

User 模型和序列化程序与Snippet 具有反向关系。现在,当我将lookup_field='id' 添加到UserSerializer (snippets = serializers.HyperlinkedRelatedField(many=True, view_name='snippet-detail', read_only=True, lookup_field='id')) 的sn-ps 属性时,就像它要求我这样做here 一样,错误仍然存​​在。

我做错了什么?我能做些什么来解决这个问题?是不是和lookup_id没有关系?

我知道我可以在我的 urlpatterns 中将 &lt;id&gt; 替换为 &lt;pk&gt;,但我想了解为什么会发生这种情况。

【问题讨论】:

一个很长的问题,但没有包含完整堆栈跟踪的基本信息。也请尽量简短。 啊,是的。我终于弄明白了。很快就会发布答案。 【参考方案1】:

我最终通过在 Django shell/python 交互式控制台中打印序列化程序来修复我的第二个异常。我得到的结果是这样的:

>>> from snippets.serializers import UserSerializer
>>> print(UserSerializer())
UserSerializer():
    url = HyperlinkedIdentityField(view_name='user-detail')
    id = IntegerField(label='ID', read_only=True)
    username = CharField(help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, validators=[<django.contrib.auth.validators.UnicodeUsernameValidator object>, <UniqueValidator(queryset=User.objects.all())>])
    snippets = HyperlinkedRelatedField(lookup_field='id', many=True, read_only=True, view_name='snippet-detail')

原来要在urlspatterns中将&lt;pk&gt;改成&lt;id&gt;,需要在UserSerializer类中添加url = HyperlinkedIdentityField(view_name='user-detail', lookup_field='id')

【讨论】:

【参考方案2】:

我刚刚遇到了同样的问题,我发现HyperlinkedIdentityField 想要在您的 URL 中插入一些占位符。但是我使用了不需要设置任何占位符的 URL。准确地说是ListCreateAPIView

url(
    r'^users/$',                  #<-- takes no params
    views.UserListView.as_view(), #<-- just prints a list 
    name="user-list"              #<-- HyperlinkedIdentityField pointing 
),                                #     here complained bitterly.

【讨论】:

以上是关于django.core.exceptions.ImproperlyConfigured:无法使用视图名称“用户详细信息”解析超链接关系的 URL的主要内容,如果未能解决你的问题,请参考以下文章