Подтвердить что ты не робот

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)),
    # ...

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

Спасибо

4b9b3361

Ответ 1

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

Ответ 2

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

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

И он решил мою проблему.

Ответ 3

Может быть, кто-то может посмотреть на это: http://www.django-rest-framework.org/api-guide/routers/

Если вы используете namespacing с гиперссылками сериализаторов, вам также необходимо убедиться, что все параметры 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')

Ответ 4

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

class BottleSerializer(serializers.HyperlinkedModelSerializer):

  user = UserSerializer()

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

Ответ 5

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

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 для рассматриваемого сериализатора. Обратите внимание, что мы определяем этот HyperlinkedIdentityField на SERIALIZER представления, которое бросает ошибку. Если моя ошибка была "Не удалось разрешить URL для гиперссылок с использованием имени представления" Study-detail ". Возможно, вы не смогли включить связанную модель в свой 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

Регистрация моего маршрутизатора для этого 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 в urls.py с добавлением "-detail" после него.

Ответ 6

Те же ошибки, но разные причины:

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

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.

Ответ 7

Если вы расширяете классы GenericViewSet и ListModelMixin и имеют ту же ошибку при добавлении поля url в виде списка, потому что вы не определяете подробный вид. Убедитесь, что вы расширяете микс RetrieveModelMixin:

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

Ответ 8

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

Ответ 9

Bottle = serializers.PrimaryKeyRelatedField(read_only = True)

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

Ответ 10

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

Ответ 11

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

Ответ 12

Я застрял в этой ошибке почти на 2 часа:

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

]

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

Ответ 13

Если вы опустите поля 'id' и 'url' в вашем сериализаторе, у вас не возникнет никаких проблем. Вы можете получить доступ к сообщениям, используя идентификатор, который в любом случае возвращается в объекте json, что упрощает реализацию вашего интерфейса.

Ответ 14

У меня была такая же проблема, я думаю, вы должны проверить

get_absolute_url

входное значение метода (** kwargs) метода объектной модели title. и использовать точное имя поля в lookup_field

Ответ 15

Я столкнулся с этой ошибкой после добавления пространства имен в мой URL

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

и добавление app_name к моему urls.py

Я решил эту проблему, указав NamespaceVersioning для моего api Framework для отдыха в settings.py моего проекта

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