python - example - django rest framework serializer
Django Rest Framework-No se pudo resolver la URL para una relación con hipervínculo utilizando el nombre de vista "usuario-detalle" (12)
Bottle = serializers.PrimaryKeyRelatedField (read_only = True)
read_only le permite representar el campo sin tener que vincularlo a otra vista del modelo.
Estoy construyendo un proyecto en Django Rest Framework donde los usuarios pueden iniciar sesión para ver su bodega. Mis ModelViewSets funcionaban bien y de repente recibí este error frustrante:
No se pudo resolver la URL para la relación de hipervínculo utilizando el nombre de vista "detalles del usuario". Es posible que no haya incluido el modelo relacionado en su API, o que haya configurado incorrectamente el atributo
lookup_field
en este campo.
La traza muestra:
[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.
Tengo un modelo de usuario de correo electrónico personalizado y el modelo de botella en models.py es:
class Bottle(models.Model):
wine = models.ForeignKey(Wine, null=False)
user = models.ForeignKey(User, null=False, related_name=''bottles'')
Mis serializadores:
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'')
Mis opiniones:
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
y finalmente la url:
router = routers.DefaultRouter()
router.register(r''bottles'', views.BottleViewSet, base_name=''bottles'')
urlpatterns = patterns('''',
url(r''^'', include(router.urls)),
# ...
No tengo una vista detallada del usuario y no veo de dónde podría surgir este problema. ¿Algunas ideas?
Gracias
Debido a que es un HyperlinkedModelSerializer
su serializador está tratando de resolver la URL del User
relacionado en su Bottle
.
Como no tiene la vista detallada del usuario, no puede hacer esto. De ahí la excepción.
- ¿No solo el registro del
UserViewSet
con el enrutador resolvería su problema? - Puede definir el campo de usuario en su
BottleSerializer
para usar explícitamente elUserSerializer
lugar de tratar de resolver la URL. Consulte la documentación del serializador sobre cómo tratar con objetos anidados para eso .
Encontré este error también y lo resolví de la siguiente manera:
La razón es que olvidé darle un "espacio de nombres a" ** - detalle "(nombre_vista, por ejemplo: usuario-detalle) Por lo tanto, Django Rest Framework no pudo encontrar esa vista.
Hay una aplicación en mi proyecto, supongo que mi nombre de proyecto es myproject
y el nombre de la aplicación es myapp
.
Hay dos archivos urls.py, uno es myproject/urls.py
y el otro es myapp/urls.py
Le doy a la aplicación un espacio de nombres en myproject/urls.py
, como:
url(r'''', include(myapp.urls, namespace="myapp")),
myapp/urls.py
enrutadores de marco de trabajo de resto en myapp/urls.py
y luego obtuve este error.
Mi solución fue proporcionar url con espacio de nombres explícitamente:
class UserSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name="myapp:user-detail")
class Meta:
model = User
fields = (''url'', ''username'')
Y resolvió mi problema.
Este código debería funcionar, también.
class BottleSerializer(serializers.HyperlinkedModelSerializer):
user = UserSerializer()
class Meta:
model = Bottle
fields = (''url'', ''wine'', ''user'')
Estuve atrapado en este error por casi 2 horas:
Se configuró incorrectamente en / api_users / users / 1 / No se pudo resolver la URL para una relación de hipervínculo utilizando el nombre de vista "user-detail". Es posible que no haya incluido el modelo relacionado en su API, o que haya configurado incorrectamente el atributo lookup_field
en este campo.
Cuando finalmente consigo la solución, pero no entiendo por qué, mi código es:
#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)),
]
pero en mis URL principales, era:
urlpatterns = [
url(r''^admin/'', admin.site.urls),
#api users
url(r''^api_users/'', include(''usersApi.users_urls'', namespace=''api'')),
]
Así que para finalmente resuelvo el problema borrando el espacio de nombres:
urlpatterns = [
url(r''^admin/'', admin.site.urls),
#api users
url(r''^api_users/'', include(''usersApi.users_urls'')),
]
Y finalmente resuelvo mi problema, para que cualquiera pueda hacerme saber por qué, mejor.
Me encontré con el mismo error cuando estaba siguiendo la guía de inicio rápido de DRF http://www.django-rest-framework.org/tutorial/quickstart/ y luego intenté buscar / usuarios. He hecho esta configuración muchas veces antes sin problemas.
Mi solución no estaba en el código sino en reemplazar la base de datos.
La diferencia entre esta instalación y las otras anteriores fue cuando creé la base de datos local.
Esta vez corri mi
./manage.py migrate
./manage.py createsuperuser
inmediatamente después de correr
virtualenv venv
. venv/bin/activate
pip install django
pip install djangorestframework
En lugar del orden exacto enumerado en la guía.
Sospeché que algo no fue creado correctamente en el DB. No me importaba mi dev db, así que lo ./manage.py migrate
y ejecuté el ./manage.py migrate
una vez más, creé un superusuario, navegué a / usuarios y el error desapareció.
Algo fue problemático con el orden de operaciones en el que configuré DRF y la base de datos.
Si está utilizando sqlite y puede probar el cambio a una base de datos nueva, entonces vale la pena intentarlo antes de diseccionar todo su código.
Me encontré con este mismo problema y lo resolví agregando generics.RetrieveAPIView
como una clase base a mi conjunto de vistas.
Mismo error, pero diferente razón:
Defino un modelo de usuario personalizado, nada nuevo campo:
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
Esta es mi función de vista:
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
Dado que no proporcioné queryset
directamente en UserViewSet
, debo establecer base_name
cuando registro este conjunto de vistas. Aquí es donde mi mensaje de error causado por el archivo 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''
Necesita un nombre base_name
como el nombre de su modelo: customuser
.
Obtuve ese error en DRF 3.7.7 cuando un valor de bala estaba vacío (es igual a '''') en la base de datos.
Otro error desagradable que causa este error es tener el nombre base innecesariamente definido en su urls.py. Por ejemplo:
router.register(r''{pathname}, views.{ViewName}ViewSet, base_name=''pathname'')
Esto causará el error mencionado anteriormente. Obtenga ese nombre base fuera de allí y vuelva a una API que funcione. El siguiente código solucionaría el error. ¡Hurra!
router.register(r''{pathname}, views.{ViewName}ViewSet)
Sin embargo, es probable que no solo haya agregado arbitrariamente el nombre base, sino que lo haya hecho porque definió una definición personalizada get_queryset () para los mandatos de Vista y Django al agregar el nombre base. En este caso, deberá definir explícitamente la ''url'' como un campo de hipervínculo para el serializador en cuestión. Observe que estamos definiendo este HyperlinkedIdentityField ON THE SERIALIZER de la vista que está generando el error. Si mi error fuera "No se pudo resolver la URL para una relación con hipervínculo utilizando el nombre de vista" detalles de estudio ". Es posible que no haya incluido el modelo relacionado en su API, o que haya configurado incorrectamente el atributo lookup_field
en este campo". Podría arreglar esto con el siguiente código.
Mi ModelViewSet (el get_queryset personalizado es la razón por la que tuve que agregar el nombre base al router.register () en primer lugar):
class StudyViewSet(viewsets.ModelViewSet):
serializer_class = StudySerializer
''''''custom get_queryset''''''
def get_queryset(self):
queryset = Study.objects.all()
return queryset
Mi registro de enrutador para este ModelViewSet en urls.py:
router.register(r''studies'', views.StudyViewSet, base_name=''studies'')
¡Y AQUÍ ESTÁ DONDE ESTÁ EL DINERO! Entonces podría resolverlo así:
class StudySerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name="studies-detail")
class Meta:
model = Study
fields = (''url'', ''name'', ''active'', ''created'',
''time_zone'', ''user'', ''surveys'')
Sí. Debe definir explícitamente este HyperlinkedIdentityField en sí mismo para que funcione. Y debe asegurarse de que el view_name
definido en el HyperlinkedIdentityField sea el mismo que definió en el nombre base_name
en urls.py con una ''-detail'' agregada después.
Quizás alguien pueda echarle un vistazo a esto: http://www.django-rest-framework.org/api-guide/routers/
Si utiliza el espacio de nombres con serializadores hipervinculados, también deberá asegurarse de que los parámetros de view_name en los serializadores reflejen correctamente el espacio de nombres. Por ejemplo:
urlpatterns = [
url(r''^forgot-password/$'', ForgotPasswordFormView.as_view()),
url(r''^api/'', include(router.urls, namespace=''api'')),
]
necesitaría incluir un parámetro como view_name=''api:user-detail''
para los campos del serializador con hipervínculo a la vista de detalles del usuario.
class UserSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name="api:user-detail")
class Meta:
model = User
fields = (''url'', ''username'')
Si está extendiendo las clases GenericViewSet y ListModelMixin , y tiene el mismo error al agregar el campo url en la vista de lista, es porque no está definiendo la vista de detalle. Asegúrese de que está extendiendo la mezcla RetrieveModelMixin :
class UserViewSet (mixins.ListModelMixin,
mixins.RetrieveModelMixin,
viewsets.GenericViewSet):