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
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.
UserViewSet
auprès du routeur ne résoudrait-il pas votre problème?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 . 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.
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')
Ce code devrait fonctionner aussi.
class BottleSerializer(serializers.HyperlinkedModelSerializer):
user = UserSerializer()
class Meta:
model = Bottle
fields = ('url', 'wine', 'user')
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.
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
.
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):
J'ai eu cette erreur sur DRF 3.7.7 quand une valeur slug était vide (égale à '') dans la base de données.
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.
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
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.
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.
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.