Django RestFramework-无法解析使用视图名称“用户详细信息”的超链接关系的 URL

我正在建立一个项目在 Django 休息框架,用户可以登录查看他们的酒窖。 我的 ModelViewSet 工作得很好,突然我得到了这个令人沮丧的错误:

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

我没有用户细节视图,也不知道这个问题从何而来。有什么想法吗?

谢谢

90975 次浏览

因为它是 HyperlinkedModelSerializer,所以序列化程序试图解析 Bottle上相关 User的 URL。
由于您没有用户详细信息视图,因此不能这样做。

  1. UserViewSet注册到路由器不会解决你的问题吗?
  2. 您可以在 BottleSerializer上定义用户字段,以显式使用 UserSerializer,而不是尝试解析 URL。看看 序列化程序文档处理该对象的嵌套对象

这个代码应该也能用。

class BottleSerializer(serializers.HyperlinkedModelSerializer):


user = UserSerializer()


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

我在遵循 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 并且能够测试更改为一个新的 DB,那么在解析所有代码之前值得尝试一下。

我也遇到了这个错误,并解决了如下问题:

原因是我忘了给“ * *-Details”(view _ name,例如: user-Details)一个名称空间。因此,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中注册了 rest 框架路由器,然后得到了这个错误。

我的解决方案是显式地为 url 提供名称空间:

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


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

解决了我的问题。

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

导致此错误的另一个讨厌的错误是在 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,而是因为您为视图定义了一个自定义 def get _ queryset () ,所以 Django 强制您添加 base _ name。在这种情况下,您需要显式地将“ url”定义为所讨论的序列化器的 HyperlinkedIdentityField。注意,我们在抛出错误的视图的 SERIALIZER 上定义了这个 HyperlinkedIdentityField。如果我的错误是“无法解决使用视图名称的超链接关系的 URL”。您可能没有在 API 中包含相关的模型,或者在这个字段中错误地配置了 lookup_field属性。”我可以用下面的代码解决这个问题。

My 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上定义的 view_name相同,后面添加了“-Details”。

Bottle = 序列化器. PrimaryKeyRelatedField (read _ only = True)

Read _ only 允许您表示字段,而不必将其链接到模型的另一个视图。

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

我定义了一个自定义用户模型,没有什么新的领域:

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

因为我没有在 UserViewSet中直接给出 queryset,所以我必须在注册这个视图集时设置 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

如果您正在扩展 GenericViewSet列表 ModelMixin类,并且在列表视图中添加 网址字段时出现了相同的错误,那是因为您没有定义详细信息视图。一定要扩展 获取 ModelMixin混合:

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

当数据库中的蛞蝓值为空(等于“)时,我在 DRF 3.7.7上得到了这个错误。

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

我被这个错误困住了将近2个小时:

在/api _ users/users/1/处配置不当 无法使用视图名称“用户详细信息”解析超链接关系的 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')),


]

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

如果您在序列化程序中省略了字段“ id”和“ url”,那么就不会有任何问题。您可以通过使用 json 对象中返回的 id 来访问这些文章,这使得实现前端变得更加容易。

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

Get _ Absolalurl

对象模型的方法输入值(* * kwargs)标题。 并在 lookup _ field 中使用精确的字段名

在将名称空间添加到 url 之后,我遇到了这个错误

 url('api/v2/', include('api.urls', namespace='v2')),

并将 app _ name 添加到 urls.py

我解决这个问题的方法是在我的项目 setings.py 中为我的 rest 框架 api 指定 NamespaceVersioning

REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.NamespaceVersioning'}

看来,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

希望这个能帮上忙。

今天,我得到了相同的错误和下面的变化救我。

改变

class BottleSerializer(serializers.HyperlinkedModelSerializer):

致:

 class BottleSerializer(serializers.ModelSerializer):

DR: 它可能就像从路由器基名中删除一个尾随‘ s’一样简单。不需要在序列化程序中定义 URL 字段。

对于最初的海报,问题只需注册 UserViewSet 即可解决,正如顶部答案中所建议的那样。

但是,如果其他人有这个问题,即使所有的视图集注册,我想我已经找出了问题出在哪里,我已经找到了一个解决方案,比这里的其他很多干净。

在我的例子中,我在尝试使用自定义 get _ queryset ()函数创建 ViewSet 时遇到了这个问题。当我用一个自定义 get _ queryset ()函数替换 ViewSet 的 queryset 字段时,出现了以下错误:

AssertionError: “ basename”参数未指定,无法从视图集自动确定名称,因为它没有“。Queryset 的属性。

因此,当然,我转到 urls.py 并修改了我的注册,使其包含如下的基名:

router.register(r'messages', MessageViewSet, basename='messages')

但后来我被这个错误击中了(正如我们在最初的帖子中看到的) :

无法使用视图名称“ message-Details”解析超链接关系的 URL。您可能没有在 API 中包含相关的模型,或者在此字段上错误地配置了“ lookup _ field”属性。

在阅读了 路由器上的 DRF 文档之后,我了解到路由器会自动为你生成两种网址模式,它们都有名称:

  1. ‘ basename-list’
  2. ‘ basename-Details’

因为我设置了 basename = ‘ message’(注意末尾的‘ s’) ,所以我的 url 模式被命名为:

  1. 「讯息列表」
  2. ‘信息-细节’

由于 DRF 正在寻找一个名为“ message-Details”的 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(...)

值得注意的是,如果使用 detail=False创建 action(输入错误?)那么这个错误就会出现,用 detail=True代替它:

@action(detail=True)
...

有点晚,但在 Django 3及以上,include不支持没有指定 app_namenamespace。检查 include的源代码,我们看到条件

if namespaces and not app_name:
....

还是从源代码中得到如下结果:

urlconf_module, app_name = arg

其中 arginclude的第一个参数。这告诉我们,我们的 include应该定义为

include((app.urls, app_name), namespace='...')

例子

假设您有一个项目 myproject和一个应用程序 myapp。然后你要建立一个地址。您应该使用一个视图集并定义一个路由器,如下所示

Myapp.urls

router.register('address', exampleviewset, basename='address')

Myproject urls

path('api/v1/', include(('myapp.urls', 'myapp'), namespace='myapp')),

序列化器 py

class AddressSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name="myapp:address-detail")
class Meta:
model = Address
fields = ('url',...)

显然,我们不能使用 fields='__all__'。我们必须显式地包含 url并列出我们需要的其余字段。

我想留下来的一切,因为-是开箱即用,所以我只是添加了一个用户序列化程序:

class UserSerializer(serializers.HyperlinkedModelSerializer):


class Meta:
model = User
fields = ['id', 'username']

观点:

class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer

并添加到网址:

router.register(r'users', UserViewSet)