web-dev-qa-db-fra.com

Django Rest Framework - Impossible de résoudre l'URL d'une relation avec lien hypertexte à l'aide du nom de vue "user-detail"

Je suis en train de construire un projet dans Django Rest Framework où les utilisateurs peuvent se connecter pour voir leur cave à vin .

Impossible de résoudre l'URL de la relation avec lien hypertexte à l'aide du nom de vue "user-detail". Vous avez peut-être échoué à inclure le modèle associé dans votre API ou configuré de manière incorrecte l'attribut lookup_field sur ce champ.

La trace montre:

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

J'ai un modèle d'utilisateur de messagerie personnalisé et le modèle de bouteille dans models.py est:

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

Mes sérialiseurs:

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

Mon point de vue:

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

et enfin l'URL:

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

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

Je n'ai pas de vue détaillée de l'utilisateur et je ne vois pas d'où ce problème pourrait provenir. Des idées?

Merci

77
bpipat

Comme il s'agit d'une HyperlinkedModelSerializer, votre sérialiseur tente de résoudre l'URL de la User correspondante sur votre Bottle.
Comme vous ne disposez pas de la vue détaillée de l'utilisateur, vous ne pouvez pas le faire. D'où l'exception.

  1. L'enregistrement de la UserViewSet auprès du routeur ne résoudrait-il pas votre problème?
  2. Vous pouvez définir le champ utilisateur sur votre BottleSerializer pour utiliser explicitement UserSerializer plutôt que d'essayer de résoudre l'URL. Voir la documentation serializer sur le traitement des objets imbriqués pour ce
75
Carlton Gibson

J'ai aussi rencontré cette erreur et l'ai résolue comme suit:

La raison en est que j'ai oublié de donner à "** - detail" (nom_vue, par exemple: utilisateur-détail) un espace de noms. Django Rest Framework n'a donc pas trouvé cette vue.

Il y a une application dans mon projet, supposons que mon nom de projet soit myproject et que le nom de l'application soit myapp.

Il existe deux fichiers urls.py, l’un est myproject/urls.py et l’autre est myapp/urls.py. Je donne à l'application un espace de noms dans myproject/urls.py, comme ceci:

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

J'ai enregistré les routeurs d'infrastructure de repos dans myapp/urls.py, puis j'ai obtenu cette erreur.

Ma solution a été de fournir explicitement l'URL avec un espace de noms:

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

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

Et cela a résolu mon problème.

43
bovenson

Peut-être que quelqu'un pourra jeter un coup d'œil à ceci: http://www.Django-rest-framework.org/api-guide/routers/

Si vous utilisez un espacement de noms avec des sérialiseurs hyperliens, vous devrez également vous assurer que tous les paramètres nom_vue sur les sérialiseurs reflètent correctement l'espace de nom. Par exemple:

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

vous auriez besoin d'inclure un paramètre tel que view_name='api:user-detail' pour les champs du sérialiseur liés à la vue détaillée de l'utilisateur.

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

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

Ce code devrait fonctionner aussi.

class BottleSerializer(serializers.HyperlinkedModelSerializer):

  user = UserSerializer()

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

Une autre erreur grave qui cause cette erreur est d'avoir le nom de base non défini inutilement dans vos urls.py. Par exemple:

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

Cela provoquera l'erreur notée ci-dessus. Obtenez ce nom de base et retournez à une API qui fonctionne. Le code ci-dessous corrigerait l'erreur. Hourra!

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

Cependant, vous n'avez probablement pas simplement ajouté le nom de base de manière arbitraire, vous l'avez peut-être fait parce que vous avez défini un def get_queryset () personnalisé pour View et donc aux commandes Django que vous ajoutez le nom de base. Dans ce cas, vous devez définir explicitement l'URL comme un champ HyperlinkedIdentityField pour le sérialiseur en question. Notez que nous définissons ce champ HyperlinkedIdentityField SUR LE SERIALIZER de la vue générant l'erreur. Si mon erreur était "Impossible de résoudre l'URL de la relation avec hyperlien à l'aide du nom de vue" study-detail ". Vous avez peut-être échoué à inclure le modèle associé dans votre API ou configuré de manière incorrecte l'attribut lookup_field sur ce champ." Je pourrais résoudre ce problème avec le code suivant. 

Mon ModelViewSet (le get_queryset personnalisé est la raison pour laquelle j'ai dû d'abord ajouter le nom de base à router.register ()): 

class StudyViewSet(viewsets.ModelViewSet):
    serializer_class = StudySerializer

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

Enregistrement de mon routeur pour ce ModelViewSet dans urls.py:

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

ET VOICI O THE L'ARGENT EST! Ensuite, je pourrais le résoudre comme suit:

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

Oui. Vous devez définir explicitement ce HyperlinkedIdentityField sur lui-même pour que cela fonctionne. Et vous devez vous assurer que le view_name défini sur HyperlinkedIdentityField est identique à celui que vous avez défini sur le base_name dans urls.py avec un «détail» ajouté après celui-ci.

9
Colton Hicks

Même erreur, mais raison différente:

Je définis un modèle d'utilisateur personnalisé, rien de nouveau champ:

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

Ceci est ma fonction de vue:

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

Étant donné que je n'ai pas donné queryset directement dans UserViewSet, je dois définir base_name lorsque j'enregistre ce groupe de vues. C’est là que mon message d’erreur causé par le fichier 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'

Vous avez besoin d’un base_name identique au nom de votre modèle - customuser.

2
Belter

Si vous étendez les classes GenericViewSet et ListModelMixin et que la même erreur se produit lors de l'ajout du champ url , c'est parce que vous ne définissez pas la vue détaillée. Assurez-vous d’étendre le RetrieveModelMixin mixin:

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

J'ai eu cette erreur sur DRF 3.7.7 quand une valeur slug était vide (égale à '') dans la base de données. 

0
mrmuggles

J'ai rencontré le même problème et je l'ai résolu en ajoutant generics.RetrieveAPIView en tant que classe de base à mon ensemble de vues.

0
Jace Browning

Si vous omettez les champs 'id' et 'url' de votre sérialiseur, vous n'aurez aucun problème. Vous pouvez accéder aux publications en utilisant de toute façon l'id qui est retourné dans l'objet json, ce qui facilite encore la mise en oeuvre de votre interface.

J'ai eu le même problème, je pense que vous devriez vérifier votre

get_absolute_url

valeur d'entrée de la méthode du modèle objet (** kwargs) title. et utiliser le nom de champ exact dans lookup_field

0
hassanzadeh.sd

J'ai rencontré la même erreur alors que je suivais le guide de démarrage rapide de DRF http://www.Django-rest-framework.org/tutorial/quickstart/ , puis que j'essayais de naviguer vers/utilisateurs. J'ai fait cette configuration plusieurs fois auparavant sans problèmes.

Ma solution ne figurait pas dans le code mais dans le remplacement de la base de données.

La différence entre cette installation et les autres auparavant était lorsque j'ai créé la base de données locale.

Cette fois j'ai couru mon

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

immédiatement après avoir couru

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

Au lieu de l'ordre exact indiqué dans le guide.

Je soupçonnais que quelque chose n'avait pas été créé correctement dans la base de données. Je me fichais de ma base de données dev donc je l'ai supprimée et exécuté la commande ./manage.py migrate une fois de plus, créé un super utilisateur, consulté le répertoire/users et l'erreur a disparu.

Quelque chose était problématique avec l'ordre des opérations dans lequel j'ai configuré DRF et la base de données.

Si vous utilisez sqlite et que vous êtes en mesure de tester le passage à une nouvelle base de données, tentez-le avant de disséquer tout votre code.

0
Ben Havilland

J'ai été coincé dans cette erreur pendant presque 2 heures:

ImproperlyConfigured at /api_users/users/1/Ne pourrait pas résoudre l'URL de la relation avec lien hypertexte à l'aide du nom de vue "users-detail". Vous avez peut-être échoué à inclure le modèle associé dans votre API ou configuré de manière incorrecte l'attribut lookup_field sur ce champ.

Quand j'obtiens enfin la solution mais que je ne comprends pas pourquoi, mon code est le suivant:

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

mais dans mes URL principales, c'était:

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    #api users
    url(r'^api_users/', include('usersApi.users_urls', namespace='api')),

]

Pour résoudre enfin le problème de l'effacement de l'espace de noms:

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    #api users
    url(r'^api_users/', include('usersApi.users_urls')),

]

Et je résous enfin mon problème, alors tout le monde peut me dire pourquoi, meilleurs.

0
Cam T

Bottle = serializers.PrimaryKeyRelatedField (read_only = True)

read_only vous permet de représenter le champ sans avoir à le lier à une autre vue du modèle.

0
Cristian Fernando