Django Rest Framework - не удалось разрешить URL для гиперссылочных отношений с использованием имени представления " user-detail"


Я строю проект в Django Rest Framework, где пользователи могут войти в систему, чтобы просмотреть свой винный погреб. Мои ModelViewSets работали просто отлично, и вдруг я получаю эту неприятную ошибку:

не удалось разрешить URL-адрес для гиперссылочной связи с использованием имени представления "user-detail". Возможно, вы не включили соответствующую модель в свой 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)),
    # ...

у меня нет подробного представления пользователя, и я не вижу, откуда эта проблема может возникнуть. Есть идеи?

спасибо

12 64

12 ответов:

потому что это HyperlinkedModelSerializer ваш сериализатор пытается разрешить URL для связанного User на Bottle.
Поскольку у вас нет подробного представления пользователя, он не может этого сделать. Отсюда и исключение.

  1. не будет просто регистрация UserViewSet с маршрутизатором решить вашу проблему?
  2. вы можете определить поле пользователя на вашем BottleSerializer чтобы явно использовать UserSerializer вместо того чтобы пытаться разрешить URL-адрес. Смотрите сериализатор документов по работе с вложенные объекты для этого.

я тоже наткнулся на эту ошибку и решил ее следующим образом:

причина в том, что я забыл дать "**-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')

и это решило мою проблему.

может быть, кто-то может взглянуть на это : 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')

этот код тоже должен работать.

class BottleSerializer(serializers.HyperlinkedModelSerializer):

  user = UserSerializer()

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

еще одна неприятная ошибка, которая вызывает эту ошибку, заключается в том, что имя base_name излишне определено в вашем urls.py например:

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

это приведет к ошибке, упомянутых выше. Получите это имя базы оттуда и вернитесь к рабочему API. Приведенный ниже код исправит ошибку. Ура!

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

однако вы, вероятно, не просто произвольно добавили base_name, вы могли бы сделать это, потому что вы определили пользовательский def get_queryset() для представления и поэтому Django мандаты, которые вы добавляете base_name. В этом случае вам нужно будет явно определить " url " как HyperlinkedIdentityField для рассматриваемого сериализатора. Обратите внимание, что мы определяем это HyperlinkedIdentityField в СЕРИАЛИЗАТОРЕ представления, которое выдает ошибку. Если моя ошибка была "не удалось разрешить URL для гиперссылочных отношений с использованием имени представления "исследование-деталь". Возможно, вы не включили соответствующую модель в свой API или неправильно настроили lookup_field атрибут в этом поле." Я мог бы исправить это с помощью следующего кода.

мой ModelViewSet (пользовательский get_queryset-это то, почему я должен был добавить base_name к маршрутизатору.регистрация() в первую очередь):

class StudyViewSet(viewsets.ModelViewSet):
    serializer_class = StudySerializer

    '''custom get_queryset'''
    def get_queryset(self):
        queryset = Study.objects.all()
        return queryset

моя регистрация маршрутизатора для этого ModelViewSet в urls.py:

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_name определяется на поле HyperlinkedIdentityField так же, как вы определили на base_name in urls.py с добавлением "- детали " после него.

та же ошибка, но другая причина:

Я определяю пользовательскую модель пользователя, ничего нового поля:

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 file:

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 и ListModelMixin классы, и имеют ту же ошибку при добавлении url поле в виде списка, это потому, что вы не определяете детальный вид. Убедитесь, что вы расширяете RetrieveModelMixin mixin:

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

я столкнулся с той же ошибкой, когда я следовал руководству быстрого запуска 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 команда еще раз, создал суперпользователя, просматривал /пользователей и ошибка исчезла.

что-то было проблематично с порядком операций, в котором я настроил DRF и db.

Если вы используете sqlite и могут протестировать изменение на новую БД, тогда стоит попробовать, прежде чем вы перейдете к разбору всего вашего кода.

бутылка = сериализатор.PrimaryKeyRelatedField (read_only=True)

read_only позволяет представлять поле без необходимости связывать его с другим представлением модели.

Я получил эту ошибку на DRF 3.7.7, когда значение slug было пустым (равно ") в базе данных.

я столкнулся с этой же проблемой и решил ее, добавив generics.RetrieveAPIView в качестве базового класса для Мой viewset.

Я застрял в этой ошибке почти на 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)),
]

но в моих основных url, это было:

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

]

и я, наконец, решить мою проблему, так что любой может дать мне знать, почему, bests.