TL;DR:我收到此错误,但不知道原因:
django.core.exceptions.ImproperlyConfigured:无法使用视图名称“user-detail”解析超链接关系的 URL。您可能未能在 API 中包含相关模型,或者错误地配置了该字段的“lookup_field”属性。
我正在经历django-rest-framework 教程 http://www.django-rest-framework.org/tutorial/3-class-based-views/目前,基于功能的视图 (FBV) 已切换为基于类、混合和通用的视图(分别为 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
需要设置为 urlpatterns http://www.django-rest-framework.org/api-guide/generic-views/#genericapiview。目前,我的 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, )
当我添加lookup_field = 'id'
在 UserDetail 和 SnippetDetail 中,异常都会自行解决。 (耶!)。但是,当我访问时http://127.0.0.1/users/1/ 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}
, not {'id':1}
。经过聊天的一些帮助后,有人向我指出this http://www.django-rest-framework.org/api-guide/generic-views/#genericapiview一点信息:
请注意,在使用超链接 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')
the User
模型和序列化器具有相反的关系Snippet
。现在,当我添加lookup_field='id'
的 snippets 属性UserSerializer
(snippets = serializers.HyperlinkedRelatedField(many=True, view_name='snippet-detail', read_only=True, lookup_field='id')
),就像它要求我这样做一样here http://www.django-rest-framework.org/api-guide/serializers/#how-hyperlinked-views-are-determined,错误是持续存在的。
我做错了什么?我可以做什么来解决这个问题?难道没有什么关系吗lookup_id
?
我明白我可以替换<id>
with <pk>
在我的 urlpatterns 中,但我想了解why这正在发生。