我正在Django Rest Framework中构建一个项目,用户可以登录查看他们的酒窖。 我的ModelViewSets工作得很好,突然间我得到了这个令人沮丧的错误:
无法使用视图名称“user-detail”解析超链接关系的URL。您可能未能在API中包含相关模型,或者在此字段上错误地配置了
lookup_field
属性。
追溯显示:
[12/Dec/2013 18:35:29] "GET /bottles/ HTTP/1.1" 500 76677
Internal Server Error: /bottles/
Traceback (most recent call last):
File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/django/core/handlers/base.py", line 114, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/viewsets.py", line 78, in view
return self.dispatch(request, *args, **kwargs)
File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 57, in wrapped_view
return view_func(*args, **kwargs)
File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/views.py", line 399, in dispatch
response = self.handle_exception(exc)
File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/views.py", line 396, in dispatch
response = handler(request, *args, **kwargs)
File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/mixins.py", line 96, in list
return Response(serializer.data)
File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/serializers.py", line 535, in data
self._data = [self.to_native(item) for item in obj]
File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/serializers.py", line 325, in to_native
value = field.field_to_native(obj, field_name)
File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/relations.py", line 153, in field_to_native
return self.to_native(value)
File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/relations.py", line 452, in to_native
raise Exception(msg % view_name)
Exception: 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.
我有自定义电子邮件用户模型,models.py中的瓶子模型是:
class Bottle(models.Model):
wine = models.ForeignKey(Wine, null=False)
user = models.ForeignKey(User, null=False, related_name='bottles')
我的序列化器:
class BottleSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Bottle
fields = ('url', 'wine', 'user')
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('email', 'first_name', 'last_name', 'password', 'is_superuser')
我的观点:
class BottleViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows bottles to be viewed or edited.
"""
queryset = Bottle.objects.all()
serializer_class = BottleSerializer
class UserViewSet(ListCreateAPIView):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = User.objects.all()
serializer_class = UserSerializer
最后是网址:
router = routers.DefaultRouter()
router.register(r'bottles', views.BottleViewSet, base_name='bottles')
urlpatterns = patterns('',
url(r'^', include(router.urls)),
# ...
我没有用户详细信息视图,但我没有看到此问题的来源。有什么想法吗?
由于
答案 0 :(得分:78)
因为HyperlinkedModelSerializer
您的序列化程序正在尝试解析User
上相关Bottle
的网址。
由于您没有用户详细信息视图,因此无法执行此操作。因此例外。
UserViewSet
来解决您的问题吗?BottleSerializer
上定义用户字段,以明确使用UserSerializer
,而不是尝试解析该网址。请参阅serializer docs on dealing with nested objects for that。 答案 1 :(得分:47)
我也遇到了这个错误并按如下方式解决了这个问题:
原因是我忘了给予" ** - 细节" (view_name,例如:user-detail)命名空间。因此,Django Rest Framework无法找到该视图。
我的项目中有一个应用,假设我的项目名称为myproject
,应用名称为myapp
。
有两个urls.py文件,一个是myproject/urls.py
,另一个是myapp/urls.py
。我在myproject/urls.py
中为应用程序提供了一个命名空间,就像:
url(r'', include(myapp.urls, namespace="myapp")),
我在myapp/urls.py
中注册了其余的框架路由器,然后出现了这个错误。
我的解决方案是明确地为url提供命名空间:
class UserSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name="myapp:user-detail")
class Meta:
model = User
fields = ('url', 'username')
它解决了我的问题。
答案 2 :(得分:16)
也许有人可以看一下:http://www.django-rest-framework.org/api-guide/routers/
如果将命名空间与超链接序列化程序一起使用,则还需要确保序列化程序上的任何view_name参数都能正确反映命名空间。例如:
urlpatterns = [
url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),
url(r'^api/', include(router.urls, namespace='api')),
]
您需要为超链接到用户详细信息视图的序列化程序字段添加view_name='api:user-detail'
等参数。
class UserSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name="api:user-detail")
class Meta:
model = User
fields = ('url', 'username')
答案 3 :(得分:10)
此代码也应该有效。
class BottleSerializer(serializers.HyperlinkedModelSerializer):
user = UserSerializer()
class Meta:
model = Bottle
fields = ('url', 'wine', 'user')
答案 4 :(得分:9)
导致此错误的另一个令人讨厌的错误是在urls.py中不必要地定义了base_name。例如:
router.register(r'{pathname}, views.{ViewName}ViewSet, base_name='pathname')
这将导致上述错误。获取base_name outta并返回到工作API。下面的代码将修复错误。万岁!
router.register(r'{pathname}, views.{ViewName}ViewSet)
但是,您可能没有随意添加base_name,您可能已经这样做了,因为您为View定义了自定义def get_queryset(),因此Django要求您添加base_name。在这种情况下,您需要明确定义' url'作为有问题的序列化程序的HyperlinkedIdentityField。请注意,我们在抛出错误的视图的SERIALIZER上定义了这个HyperlinkedIdentityField。如果我的错误是"无法使用视图名称解析超链接关系的URL" study-detail"。您可能未能在API中包含相关模型,或者在此字段上错误地配置了lookup_field
属性。"我可以使用以下代码修复此问题。
我的ModelViewSet(自定义get_queryset是我必须首先将base_name添加到router.register()的原因):
class StudyViewSet(viewsets.ModelViewSet):
serializer_class = StudySerializer
'''custom get_queryset'''
def get_queryset(self):
queryset = Study.objects.all()
return queryset
我在urls.py中的此ModelViewSet的路由器注册:
router.register(r'studies', views.StudyViewSet, base_name='studies')
和这里的钱在哪里!然后我可以这样解决它:
class StudySerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name="studies-detail")
class Meta:
model = Study
fields = ('url', 'name', 'active', 'created',
'time_zone', 'user', 'surveys')
是的。您必须在其自身上明确定义此HyperlinkedIdentityField才能使其正常工作。并且您需要确保HyperlinkedIdentityField上定义的view_name
与您在urls.py中的base_name
上定义的set(permutations(p))
相同,并且' -detail'在它之后添加。
答案 5 :(得分:4)
今天,我遇到了同样的错误,下面的更改可以挽救我。
更改
class BottleSerializer(serializers.HyperlinkedModelSerializer):
收件人:
class BottleSerializer(serializers.ModelSerializer):
答案 6 :(得分:2)
TL;DR:它可能就像从路由器基本名称中删除尾随的 's' 一样简单。无需在序列化程序中定义 url 字段。
对于原始海报,只需按照顶部答案中的建议注册 UserViewSet 即可解决该问题。
但是,如果其他人即使在所有 ViewSet 都已注册的情况下遇到此问题,我想我已经弄清楚出了什么问题,并且我找到了一个比这里的许多其他解决方案更简洁的解决方案。
就我而言,我在尝试使用自定义 get_queryset() 函数创建 ViewSet 后遇到了此问题。当我用自定义 get_queryset() 函数替换 ViewSet 的查询集字段时,我遇到了这个错误:
<块引用>断言错误:未指定 `basename` 参数,无法从视图集自动确定名称,因为它没有 `.queryset` 属性。
所以,当然,我去了 urls.py 并修改了我的注册以包含一个基本名称:
router.register(r'messages', MessageViewSet, basename='messages')
但是后来我遇到了这个错误(正如我们在原始帖子中看到的那样):
<块引用>无法使用视图名称“消息详细信息”解析超链接关系的 URL。您可能没有在 API 中包含相关模型,或者在此字段上错误地配置了 `lookup_field` 属性。
阅读DRF docs on routers后,我了解到路由器会自动为您生成两个url模式,它们有名称:
因为我设置了 basename='messages'(注意末尾的 's'),我的 url 模式被命名为:
由于 DRF 正在查找名为“message-detail”的 url 模式(请注意此处缺少“s”),我意识到我可以通过从基本名称中删除尾随的“s”来解决此问题强> 如此:
router.register(r'messages', MessageViewSet, basename='message')
我最终的序列化器和 ViewSet 实现就这么简单!
class MessageSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Message
fields = ['url', 'message', 'timestamp', 'sender', ...]
class MessageViewSet(viewsets.ModelViewSet):
serializer_class = MessageSerializer
def get_queryset(self):
return Message.objects.filter(...)
答案 7 :(得分:2)
相同错误,但原因不同:
我定义了一个自定义用户模型,没有新字段:
from django.contrib.auth.models import (AbstractUser)
class CustomUser(AbstractUser):
"""
custom user, reference below example
https://github.com/jonathanchu/django-custom-user-example/blob/master/customuser/accounts/models.py
# original User class has all I need
# Just add __str__, not rewrite other field
- id
- username
- password
- email
- is_active
- date_joined
- method, email_user
"""
def __str__(self):
return self.username
这是我的观点功能:
from rest_framework import permissions
from rest_framework import viewsets
from .models import (CustomUser)
class UserViewSet(viewsets.ModelViewSet):
permission_classes = (permissions.AllowAny,)
serializer_class = UserSerializer
def get_queryset(self):
queryset = CustomUser.objects.filter(id=self.request.user.id)
if self.request.user.is_superuser:
queryset = CustomUser.objects.all()
return queryset
由于我没有直接在queryset
中提供UserViewSet
,因此我必须在注册此视图集时设置base_name
。这是由urls.py
文件引起的错误消息:
from myapp.views import (UserViewSet)
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'users', UserViewSet, base_name='customuser') # <--base_name needs to be 'customuser' instead of 'user'
您需要base_name
与模型名称相同 - customuser
。
答案 8 :(得分:1)
如果您要扩展 GenericViewSet 和 ListModelMixin 类,并且在列表视图中添加 url 字段时出现相同的错误,这是因为你没有定义细节视图。确保您正在扩展 RetrieveModelMixin mixin:
class UserViewSet (mixins.ListModelMixin,
mixins.RetrieveModelMixin,
viewsets.GenericViewSet):
答案 9 :(得分:1)
看来HyperlinkedModelSerializer
与路径namespace
不同。在我的应用程序中,我进行了两项更改。
# rootapp/urls.py
urlpatterns = [
# path('api/', include('izzi.api.urls', namespace='api'))
path('api/', include('izzi.api.urls')) # removed namespace
]
在导入的urls文件中
# app/urls.py
app_name = 'api' // removed the app_name
希望这会有所帮助。
答案 10 :(得分:0)
值得注意的是,如果您使用 action
(打字错误?)创建 detail=False
,则会引发此错误,请将其替换为 detail=True
:
@action(detail=True)
...
答案 11 :(得分:0)
在我的网址中添加命名空间后,我遇到了这个错误
url('api/v2/', include('api.urls', namespace='v2')),
并将app_name添加到我的urls.py
我通过在项目的settings.py中为我的其余框架api指定NamespaceVersioning来解决此问题
REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.NamespaceVersioning'}
答案 12 :(得分:0)
我遇到了同样的问题,我认为您应该检查您的
get_absolute_url
对象模型的方法输入值(** kwargs)标题。 并在lookup_field中使用确切的字段名称
答案 13 :(得分:0)
如果您从序列化程序中省略了字段“ id”和“ url”,则不会有任何问题。无论如何,您都可以使用json对象中返回的ID来访问帖子,这使实现前端变得更加容易。
答案 14 :(得分:0)
我在这个错误中停留了将近2个小时:
在/ api_users / users / 1 /中配置不正确
无法使用视图名称“ users-detail”解析超链接关系的URL。您可能无法在API中包含相关模型,或者在此字段上错误地配置了lookup_field
属性。
当我终于得到解决方案但不知道为什么时,所以我的代码是:
#models.py
class Users(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=50, blank=False, null=False)
email = models.EmailField(null=False, blank=False)
class Meta:
verbose_name = "Usuario"
verbose_name_plural = "Usuarios"
def __str__(self):
return str(self.name)
#serializers.py
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Users
fields = (
'id',
'url',
'name',
'email',
'description',
'active',
'age',
'some_date',
'timestamp',
)
#views.py
class UserViewSet(viewsets.ModelViewSet):
queryset = Users.objects.all()
serializer_class = UserSerializer
#urls_api.py
router = routers.DefaultRouter()
router.register(r'users',UserViewSet, base_name='users')
urlpatterns = [
url(r'^', include(router.urls)),
]
但是在我的主要网址中,是:
urlpatterns = [
url(r'^admin/', admin.site.urls),
#api users
url(r'^api_users/', include('usersApi.users_urls', namespace='api')),
]
所以最终我解决了擦除命名空间的问题:
urlpatterns = [
url(r'^admin/', admin.site.urls),
#api users
url(r'^api_users/', include('usersApi.users_urls')),
]
我终于解决了我的问题,所以任何人都可以让我知道为什么,最好。
答案 15 :(得分:0)
我遇到了同样的问题,并通过将generics.RetrieveAPIView
作为基类添加到我的视图集来解决了这个问题。
答案 16 :(得分:0)
当数据库中的slug值为空(等于'')时,我在DRF 3.7.7上出现了该错误。
答案 17 :(得分:0)
Bottle = serializers.PrimaryKeyRelatedField(read_only = True)
read_only允许您表示字段,而无需将其链接到模型的另一个视图。
答案 18 :(得分:0)
我在遵循DRF快速入门指南时遇到了同样的错误 http://www.django-rest-framework.org/tutorial/quickstart/然后尝试浏览到/ users。我之前已多次完成此设置而没有任何问题。
我的解决方案不在代码中,而是替换数据库。
此安装与其他安装之间的区别在于我创建本地数据库。
这次我跑了
./manage.py migrate
./manage.py createsuperuser
运行后立即
virtualenv venv
. venv/bin/activate
pip install django
pip install djangorestframework
而不是指南中列出的确切顺序。
我怀疑在数据库中没有正确创建某些内容。我不关心我的dev db所以我删除了它并再次运行./manage.py migrate
命令,创建了一个超级用户,浏览到/ users并且错误消失了。
我配置DRF和db的操作顺序有问题。
如果您正在使用sqlite并且能够测试更改为新的数据库,则在分析所有代码之前,值得尝试。