django.core.exceptions.不正确配置:无法使用视图名称解析超链接关系的 URL "user-detail"



TL;DR:我得到这个错误,不知道为什么:

django.core.exceptions。无法解析使用视图名"user-detail"的超链接关系的URL。您可能没有在API中包含相关的模型,或者错误地配置了该字段的'lookup_field'属性。

我正在通过django-rest-framework教程,我目前处于基于函数的视图(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_field需要在url模式中设置为。目前,我的url .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:为'user-detail'反转参数'()'和关键字参数'{'pk': 1}'未找到。2模式(s)尝试:['用户/(? P[0 - 9] +) 。(? P [a-z0-9] +)/?美元","用户/(? P[0 - 9] +)/美元)

在处理上述异常时,出现了另一个异常:

django.core.exceptions。不正确配置:无法解析URL使用视图名"user-detail"的超链接关系。你可能有未能在API中包含相关模型,或错误在此字段上配置了'lookup_field'属性。

我发现有趣的是第一个异常的kwargs是{'pk': 1},而不是{'id':1}。在一些聊天的帮助下,有人给我指出了这条信息:

请注意,当使用超链接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'))的snippets属性时,就像它要求我在这里这样做一样,错误是持久的。

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

我知道我可以用<pk>代替<id>在我的urlpatterns,但我想了解为什么这是发生的

看完教程后遇到这个问题的人,这里有答案。

改变这些行

router.register(r'snippets', views.SnippetViewSet,basename="snippets")
router.register(r'users', views.UserViewSet,basename="users")

To these(注意单数基名)

router.register(r'snippets', views.SnippetViewSet,basename="snippet")
router.register(r'users', views.UserViewSet,basename="user")

如果你完全按照教程所写的那样去做,它会生成这些路由器url(注意snippets-details)。这就是导致错误

的原因
<URLPattern '^snippets.(?P<format>[a-z0-9]+)/?$' [name='snippets-list']>
<URLPattern '^snippets/(?P<pk>[^/.]+)/$' [name='snippets-detail']>
<URLPattern '^snippets/(?P<pk>[^/.]+).(?P<format>[a-z0-9]+)/?$' [name='snippets-detail']>
<URLPattern '^snippets/(?P<pk>[^/.]+)/highlight/$' [name='snippets-highlight']>
<URLPattern '^snippets/(?P<pk>[^/.]+)/highlight.(?P<format>[a-z0-9]+)/?$' [name='snippets-highlight']>

通过在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')

事实证明,要在urlpatterns中将<pk>更改为<id>,您需要在UserSerializer类中添加url = HyperlinkedIdentityField(view_name='user-detail', lookup_field='id')

我刚刚遇到了同样的问题,我发现,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.

相关内容

最新更新