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


108

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

无法使用视图名称“用户详细信息”解析超链接关系的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

最后是URL:

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

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

我没有用户详细信息视图,也看不到此问题可能来自何处。有任何想法吗?

谢谢

Answers:


96

由于是HyperlinkedModelSerializer序列化程序,因此您的序列化程序正在尝试解析与User上相关的URL Bottle
由于您没有用户详细信息视图,因此无法执行此操作。因此,例外。

  1. 不仅仅是UserViewSet在路由器上注册可以解决您的问题吗?
  2. 您可以在自己的用户字段上定义BottleSerializer以显式使用,UserSerializer而不是尝试解析URL。请参阅有关处理嵌套对象序列化器文档

1
非常感谢,我已经在路由器中注释掉了UserViewSet,就解决了!
bpipat

5
那就是要点----明确地做---很多魔术就是很多时间的浪费。
andilabs

您能否指出我的项目中配置错误的内容?
JJD

@GrijeshChauhan-谢谢!现在已修复。
卡尔顿·吉布森

它不起作用的原因是,django希望在当前视图中为参数User显示来自User的相关数据。通常,它会选择可用值的列表。由于未定义UserViewSet,因此无法提取详细信息以呈现网页。在默认路由器下添加UserViewSet并重新注册使渲染所有组件的过程变得完整。
Doogle

65

我也遇到了此错误,并按以下方式解决了该错误:

原因是我忘记给“ **-detail”(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')

它解决了我的问题。


@boveson,这就像一个魅力!谢谢您解决了我这边数小时的无奈。
lmiguelvargasf

这也使它为我工作。我这一边的另一个重要要点是Route中base_name的正确拼写!
麦琪

1
这里的关键是名称空间前缀防止反向工作
。..– boatcoder

我遇到了这样的问题,经过3个小时的搜索,此答案解决了我的问题!@bovenson
鲸鱼52Hz,

或者您可以按照drf的建议使用extra_kwargs:extra_kwargs = {'url': {'view_name': 'myapp:user-detail'}}
ChrisRob

19

也许有人可以看看这个: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')

1
综上所述,为您的api提供名称空间会导致标题错误,除非您希望在许多地方进行更改,否则您可能不想这样做。
标记

为我工作!我urls.py是在newsite项目中双重嵌套的:(1)newsite/urls.py(由django创建)(2)polls/urls.py(3)polls/api/v1/urls.py ............我不得不使用url = serializers.HyperlinkedIdentityField(view_name="polls:polls_api:user-detail")
Grijesh Chauhan

12

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

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

这将导致上述错误。在那里获取该base_name并返回到正常工作的API。下面的代码将修复该错误。万岁!

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

但是,您可能不仅随便添加了base_name,还因为您为View定义了自定义def get_queryset(),所以Django要求您添加base_name。在这种情况下,您需要为相关的序列化程序显式定义“ url”作为HyperlinkedIdentityField。注意,我们在抛出错误的视图的SERIALIZER上定义了此HyperlinkedIdentityField。如果我的错误是“无法使用视图名称“ study-detail”解析超链接关系的URL。您可能无法在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才能起作用。而且,您需要确保view_nameHyperlinkedIdentityField上的定义与base_nameurls.py中的定义相同,并在其后添加“ -detail”。


2
这对我有用,但是我必须全程走<app_name>:studies-detail。例如,如果我的应用程序被调用tanks,则完整路径为HyperlinkedIdentityField(view_name="tanks:studies-detail")。为了弄清楚这一点,我使用了django-exensions show_urls命令,以查看完整的路由以及路由器自动创建的标签。
dtasev

10

该代码也应该起作用。

class BottleSerializer(serializers.HyperlinkedModelSerializer):

  user = UserSerializer()

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

3
值得注意的是UserSerializer必须实施(尚未准备好导入),如django-rest-framework.org/api-guide/serializers
Caumons 2014年

这对我有用,但要使其正常工作,我必须将router.register(r'bottles',views.BottleViewSet,base_name ='bottles')更改为router.register(r'bottles',views.BottleViewSet)。我不知道为什么需要此更改。
manpikin

4

将名称空间添加到我的网址后,我遇到了此错误

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

3

今天,我遇到了同样的错误,下面的更改可以挽救我。

更改

class BottleSerializer(serializers.HyperlinkedModelSerializer):

至:

 class BottleSerializer(serializers.ModelSerializer):

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


旧帖子,但是您的注释“#<-base_name必须是'customuser'而不是'user'”,这才使我省了很多。谢谢!
HannonCésar

1

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

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

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

希望这可以帮助。


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

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

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

我配置DRF和db的操作顺序出现了问题。

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



0

当数据库中的段标值为空(等于”)时,我在DRF 3.7.7上收到该错误。


0

我遇到了同样的问题,并通过将其generics.RetrieveAPIView作为基类添加到我的视图集来解决了该问题。


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

]

我终于解决了我的问题,所以任何人都可以让我知道为什么,最好。


0

如果您在序列化程序中省略了字段“ id”和“ url”,则不会有任何问题。无论如何,您都可以使用json对象中返回的ID来访问帖子,这使实现前端变得更加容易。


0

我有同样的问题,我想你应该检查一下

get_absolute_url

对象模型的方法输入值(** kwargs)标题。并在lookup_field中使用确切的字段名称

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.