Python Django Rest Framework - 无法使用视图名称“user-detail”解析超链接关系的 URL

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20550598/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 20:42:47  来源:igfitidea点击:

Django Rest Framework - Could not resolve URL for hyperlinked relationship using view name "user-detail"

pythondjangodjango-rest-framework

提问by bpipat

I am building a project in Django Rest Framework where users can login to view their wine cellar. My ModelViewSets were working just fine and all of a sudden I get this frustrating error:

我正在 Django Rest Framework 中构建一个项目,用户可以在其中登录以查看他们的酒窖。我的 ModelViewSets 工作得很好,突然间我收到了这个令人沮丧的错误:

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_fieldattribute on this field.

无法使用视图名称“用户详细信息”解析超链接关系的 URL。您可能没有在 API 中包含相关模型,或者错误地配置了lookup_field该字段的属性。

The traceback shows:

回溯显示:

    [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.

I have a custom email user model and the bottle model in models.py is:

我有一个自定义电子邮件用户模型,models.py 中的瓶子模型是:

class Bottle(models.Model):    
      wine = models.ForeignKey(Wine, null=False)
      user = models.ForeignKey(User, null=False, related_name='bottles')

My serializers:

我的序列化程序:

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')

My views:

我的观点:

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

and finally the url:

最后是网址:

router = routers.DefaultRouter()
router.register(r'bottles', views.BottleViewSet, base_name='bottles')

urlpatterns = patterns('',
    url(r'^', include(router.urls)),
    # ...

I don't have a user detail view and I don't see where this issue could come from. Any ideas?

我没有用户详细信息视图,我不知道这个问题可能来自哪里。有任何想法吗?

Thanks

谢谢

采纳答案by Carlton Gibson

Because it's a HyperlinkedModelSerializeryour serializer is trying to resolve the URL for the related Useron your Bottle.
As you don't have the user detail view it can't do this. Hence the exception.

因为它是一个HyperlinkedModelSerializer你的串行试图解析为相关的URLUser在你的Bottle
由于您没有用户详细信息视图,因此无法执行此操作。因此例外。

  1. Would not just registering the UserViewSetwith the router solve your issue?
  2. You could define the user field on your BottleSerializerto explicitly use the UserSerializerrather than trying to resolve the URL. See the serializer docs on dealing with nested objects for that.
  1. UserViewSet在路由器上注册就不能解决您的问题吗?
  2. 您可以定义用户字段BottleSerializer以显式使用UserSerializer而不是尝试解析 URL。请参阅有关处理嵌套对象序列化程序文档

回答by caglar

This code should work, too.

这段代码也应该有效。

class BottleSerializer(serializers.HyperlinkedModelSerializer):

  user = UserSerializer()

  class Meta:
    model = Bottle
    fields = ('url', 'wine', 'user')

回答by Ben Havilland

I ran into the same error while I was following the DRF quickstart guide http://www.django-rest-framework.org/tutorial/quickstart/and then attempting to browse to /users. I've done this setup many times before without problems.

我在遵循 DRF 快速入门指南http://www.django-rest-framework.org/tutorial/quickstart/然后尝试浏览到 /users 时遇到了同样的错误 。我以前做过很多次这个设置,没有问题。

My solution was not in the code but in replacing the database.

我的解决方案不在代码中,而是在替换数据库中。

The difference between this install and the others before was when I created the local database.

此安装与之前的其他安装之间的区别在于我创建本地数据库时。

This time I ran my

这次我跑了我的

./manage.py migrate
./manage.py createsuperuser

immediately after running

运行后立即

virtualenv venv
. venv/bin/activate
pip install django
pip install djangorestframework

Instead of the exact order listed in the guide.

而不是指南中列出的确切顺序。

I suspected something wasn't properly created in the DB. I didn't care about my dev db so I deleted it and ran the ./manage.py migratecommand once more, created a super user, browsed to /users and the error was gone.

我怀疑在数据库中没有正确创建某些东西。我不关心我的开发数据库,​​所以我删除了它并./manage.py migrate再次运行命令,创建了一个超级用户,浏览到 /users 并且错误消失了。

Something was problematic with the order of operations in which I configured DRF and the db.

我配置 DRF 和数据库的操作顺序有问题。

If you are using sqlite and are able to test changing to a fresh DB then it's worth an attempt before you go dissecting all of your code.

如果您正在使用 sqlite 并且能够测试更改为新数据库,那么在剖析所有代码之前值得一试。

回答by bovenson

I came across this error too and solved it as follows:

我也遇到了这个错误,解决方法如下:

The reason is I forgot giving "**-detail" (view_name, e.g.: user-detail) a namespace. So, Django Rest Framework could not find that view.

原因是我忘记给 "**-detail" (view_name, eg: user-detail) 一个命名空间。因此,Django Rest Framework 找不到该视图。

There is one app in my project, suppose that my project name is myproject, and the app name is myapp.

我的项目中有一个应用程序,假设我的项目名称是myproject,应用程序名称是myapp

There is two urls.py file, one is myproject/urls.pyand the other is myapp/urls.py. I give the app a namespace in myproject/urls.py, just like:

有两个 urls.py 文件,一个myproject/urls.pymyapp/urls.py. 我给应用程序一个命名空间myproject/urls.py,就像:

url(r'', include(myapp.urls, namespace="myapp")),

I registered the rest framework routers in myapp/urls.py, and then got this error.

我在 中注册了其余框架路由器myapp/urls.py,然后出现此错误。

My solution was to provide url with namespace explicitly:

我的解决方案是明确提供带有命名空间的 url:

class UserSerializer(serializers.HyperlinkedModelSerializer):
    url = serializers.HyperlinkedIdentityField(view_name="myapp:user-detail")

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

And it solved my problem.

它解决了我的问题。

回答by HymanPy

Maybe someone can have a look at this : http://www.django-rest-framework.org/api-guide/routers/

也许有人可以看看这个:http: //www.django-rest-framework.org/api-guide/routers/

If using namespacing with hyperlinked serializers you'll also need to ensure that any view_name parameters on the serializers correctly reflect the namespace. For example:

如果将命名空间与超链接序列化器一起使用,您还需要确保序列化器上的任何 view_name 参数正确反映命名空间。例如:

urlpatterns = [
    url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),
    url(r'^api/', include(router.urls, namespace='api')),
]

you'd need to include a parameter such as view_name='api:user-detail'for serializer fields hyperlinked to the user detail view.

您需要包含一个参数,例如view_name='api:user-detail'超链接到用户详细信息视图的序列化程序字段。

class UserSerializer(serializers.HyperlinkedModelSerializer):
    url = serializers.HyperlinkedIdentityField(view_name="api:user-detail")

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

回答by Colton Hicks

Another nasty mistake that causes this error is having the base_name unnecessarily defined in your urls.py. For example:

导致此错误的另一个严重错误是在 urls.py 中不必要地定义了 base_name。例如:

router.register(r'{pathname}', views.{ViewName}ViewSet, base_name='pathname')

This will cause the error noted above. Get that base_name outta there and get back to a working API. The code below would fix the error. Hooray!

这将导致上述错误。获取那个 base_name 并返回到可用的 API。下面的代码将修复错误。万岁!

router.register(r'{pathname}', views.{ViewName}ViewSet)

However, you probably didn't just arbitrarily add the base_name, you might have done it because you defined a custom def get_queryset() for the View and so Django mandates that you add the base_name. In this case you'll need to explicitly define the 'url' as a HyperlinkedIdentityField for the serializer in question. Notice we are defining this HyperlinkedIdentityField ON THE SERIALIZER of the view that is throwing the error. If my error were "Could not resolve URL for hyperlinked relationship using view name "study-detail". You may have failed to include the related model in your API, or incorrectly configured the lookup_fieldattribute on this field." I could fix this with the following code.

但是,您可能不只是随意添加 base_name,您可能已经这样做了,因为您为视图定义了自定义 def get_queryset(),因此 Django 要求您添加 base_name。在这种情况下,您需要将“url”明确定义为相关序列化程序的 HyperlinkedIdentityField。请注意,我们在抛出错误的视图的序列化器上定义了这个 HyperlinkedIdentityField。如果我的错误是“无法使用视图名称“study-detail”解析超链接关系的 URL。您可能没有在 API 中包含相关模型,或者错误地配置了lookup_field该字段的属性。我可以用下面的代码解决这个问题。

My ModelViewSet (the custom get_queryset is why I had to add the base_name to the router.register() in the first place):

我的 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

My router registration for this ModelViewSet in urls.py:

我在 urls.py 中为此 ModelViewSet 注册的路由器:

router.register(r'studies', views.StudyViewSet, base_name='studies')

AND HERE'S WHERE THE MONEY IS! Then I could solve it like so:

这就是钱!然后我可以像这样解决它:

class StudySerializer(serializers.HyperlinkedModelSerializer):
    url = serializers.HyperlinkedIdentityField(view_name="studies-detail")
    class Meta:
        model = Study
        fields = ('url', 'name', 'active', 'created',
              'time_zone', 'user', 'surveys')

Yep. You have to explicitly define this HyperlinkedIdentityField on itself for it to work. And you need to make sure that the view_namedefined on the HyperlinkedIdentityField is the same as you defined on the base_namein urls.py with a '-detail' added after it.

是的。您必须在其自身上显式定义此 HyperlinkedIdentityField 才能使其工作。并且您需要确保view_name在 HyperlinkedIdentityField 上定义的与您base_name在 urls.py 中定义的相同,并在其后添加了“-detail”。

回答by Cristian Fernando

Bottle = serializers.PrimaryKeyRelatedField(read_only=True)

Bottle = serializers.PrimaryKeyRelatedField(read_only=True)

read_only allows you to represent the field without having to link it to another view of the model.

read_only 允许您表示该字段,而无需将其链接到模型的另一个视图。

回答by Belter

Same Error, but different reason:

同样的错误,但不同的原因:

I define a custom user model, nothing new field:

我定义了一个自定义用户模型,没有什么新字段:

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

This is my view function:

这是我的视图函数:

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

Since I didn't give querysetdirectly in UserViewSet, I have to set base_namewhen I register this viewset. This is where my error message caused by urls.pyfile:

由于我没有queryset直接给UserViewSet,所以base_name我注册这个viewset的时候要设置。这是我由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'

You need a base_namesame as your model name - customuser.

您需要一个base_name与您的型号名称相同的名称 - customuser.

回答by Rowinson Gallego

If you're extending the GenericViewSetand ListModelMixinclasses, and have the same error when adding the urlfield in the list view, it's because you're not defining the detail view. Be sure you're extending the RetrieveModelMixinmixin:

如果您正在扩展GenericViewSetListModelMixin类,并且在列表视图中添加url字段时出现相同的错误,那是因为您没有定义详细视图。确保您正在扩展RetrieveModelMixin混合:

class UserViewSet (mixins.ListModelMixin,
                   mixins.RetrieveModelMixin,
                   viewsets.GenericViewSet):

回答by mrmuggles

I got that error on DRF 3.7.7 when a slug value was empty (equals to '') in the database.

当数据库中的 slug 值为空(等于 '')时,我在 DRF 3.7.7 上遇到了该错误。