TL; DR:我收到此错误并且不知道原因:
django.core.exceptions.ImproperlyConfigured:无法使用视图名称" user-detail"解析超链接关系的URL。您可能未能在API中包含相关模型,或者未正确配置' lookup_field'该字段的属性。
我正在浏览django-rest-framework tutorial,目前处于基于功能的视图(FBV)切换到class,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
needs 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:反向&#39;用户详细信息&#39;同 论证&#39;()&#39;和关键字参数&#39; {&#39; pk&#39;:1}&#39;未找到。 2 模式尝试:[&#39;用户/(?P [0-9] +)\。(?P [a-z0-9] +)/?$&#39;, &#39;用户/ / $&#39(P [0-9] +);]
在处理上述异常期间,发生了另一个异常:
django.core.exceptions.ImproperlyConfigured:无法解析网址 使用视图名称&#34; user-detail&#34;的超链接关系。你可能有 未能在您的API中包含相关模型,或者说错误 配置了&#39; lookup_field&#39;该字段的属性。
我觉得有趣的是第一个例外的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')
)的片段属性时,就像它要求我这样做here一样,错误是持久的。
我做错了什么?我该怎么做才能解决这个问题?它与lookup_id
没有任何关系吗?
我知道我可以在我的网址中用<id>
替换<pk>
,但我想了解为什么这种情况发生。
答案 0 :(得分:0)
我最终通过在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中将<pk>
更改为<id>
,您需要在url = HyperlinkedIdentityField(view_name='user-detail', lookup_field='id')
类中添加UserSerializer
。
答案 1 :(得分:0)
我遇到了同样的问题,我发现,HyperlinkedIdentityField
想要在您的网址中插入一些占位符。但是我使用了不需要任何占位符的URL。确切地说ListCreateAPIView
:
url(
r'^users/$', #<-- takes no params
views.UserListView.as_view(), #<-- just prints a list
name="user-list" #<-- HyperlinkedIdentityField pointing
), # here complained bitterly.