color - plt plot python title
AssertionError: `HyperlinkedIdentityField` requiere la solicitud en el contexto del serializador (4)
Me encontré con el mismo problema. Mi enfoque es eliminar ''url'' de Meta.fields en serializer.py.
Quiero crear una relación de many-to-many
donde una persona puede estar en muchos clubes y un club puede tener muchas personas. models.py
los models.py
y serializers.py
para la siguiente lógica, pero cuando intento serializarlo en el símbolo del sistema, aparece el siguiente error: ¿qué estoy haciendo mal aquí? Ni siquiera tengo un HyperlinkedIdentityField
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "C:/Users/user/corr/lib/site-packages/rest_framework/serializers.py", line 503, in data
ret = super(Serializer, self).data
File "C:/Users/user/corr/lib/site-packages/rest_framework/serializers.py", line 239, in data
self._data = self.to_representation(self.instance)
File "C:/Users/user/corr/lib/site-packages/rest_framework/serializers.py", line 472, in to_representation
ret[field.field_name] = field.to_representation(attribute)
File "C:/Users/user/corr/lib/site-packages/rest_framework/relations.py", line 320, in to_representation"the serializer." % self.__class__.__name__
AssertionError: `HyperlinkedIdentityField` requires the request in the serializer context. Add `context={''request'': request}` when instantiating the serializer.
models.py
class Club(models.Model):
club_name = models.CharField(default='''',blank=False,max_length=100)
class Person(models.Model):
person_name = models.CharField(default='''',blank=False,max_length=200)
clubs = models.ManyToManyField(Club)
serializers.py
class ClubSerializer(serializers.ModelSerializer):
class Meta:
model = Club
fields = (''url'',''id'',''club_name'',''person'')
class PersonSerializer(serializers.ModelSerializer):
clubs = ClubSerializer()
class Meta:
model = Person
fields = (''url'',''id'',''person_name'',''clubs'')
views.py
class ClubDetail(generics.ListCreateAPIView):
serializer_class = ClubSerializer
def get_queryset(self):
club = Clubs.objects.get(pk=self.kwargs.get(''pk'',None))
persons = Person.objects.filter(club=club)
return persons
class ClubList(generics.ListCreateAPIView):
queryset = Club.objects.all()
serializer_class = ClubSerializer
class PersonDetail(generics.RetrieveUpdateDestroyAPIView):
serializer_class = PersonSerializer
def get_object(self):
person_id = self.kwargs.get(''pk'',None)
return Person.objects.get(pk=person_id)
Inspeccionar el serializador creado me da esto -
PersonSerializer(<Person: fd>):
url = HyperlinkedIdentityField(view_name=''person-detail'')
id = IntegerField(label=''ID'', read_only=True)
person_name = CharField(max_length=200, required=False)
clubs = ClubSerializer():
url = HyperlinkedIdentityField(view_name=''club-detail'')
id = IntegerField(label=''ID'', read_only=True)
club_name = CharField(max_length=100, required=False)
pero serializer.data
me da el error
*************************************** Me di cuenta de que el error podría ser debido a los patrones de url
, así que agregué los siguientes patrones de url, pero sigo recibiendo el error -
urlpatterns = format_suffix_patterns([
url(r''^$'', views.api_root),
url(r''^clubs/$'',
views.ClubList.as_view(),
name=''club-list''),
url(r''^clubs/(?P<pk>[0-9]+)/persons/$'',
views.ClubDetail.as_view(),
name=''club-detail''),
url(r''^person/(?P<pk>[0-9]+)/$'',
views.PersonDetail.as_view(),
name=''person-detail''),
])
Recibirá este error ya que HyperlinkedIdentityField
espera recibir una request
en el context
del serializador para que pueda crear URL absolutas. Cuando está inicializando su serializador en la línea de comandos, no tiene acceso para solicitar y, por lo tanto, recibe un error.
Si necesita verificar su serializador en la línea de comandos, deberá hacer algo como esto:
from rest_framework.request import Request
from rest_framework.test import APIRequestFactory
from .models import Person
from .serializers import PersonSerializer
factory = APIRequestFactory()
request = factory.get(''/'')
serializer_context = {
''request'': Request(request),
}
p = Person.objects.first()
s = PersonSerializer(instance=p, context=serializer_context)
print s.data
Su campo url se vería algo así como http://testserver/person/1/
.
Siguiendo la respuesta de Slipstream, views.py
mi views.py
introduciendo el contexto y ahora funciona.
class UserViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = User.objects.all().select_related(''profile'').order_by(''-date_joined'')
serializer_class = UserSerializer
@list_route(methods=[''get''], url_path=''username/(?P<username>/w+)'')
def getByUsername(self, request, username):
serializer_context = {
''request'': request,
}
user = get_object_or_404(User, username=username)
return Response(UserSerializer(user, context=serializer_context).data, status=status.HTTP_200_OK)
Tengo dos soluciones ...
urls.py
1) Si está utilizando un router.register, puede agregar el nombre base :
router.register(r''users'', views.UserViewSet, base_name=''users'')
urlpatterns = [
url(r'''', include(router.urls)),
]
2) Si tienes algo como esto:
urlpatterns = [
url(r''^user/$'', views.UserRequestViewSet.as_view()),
]
Tienes que pasar el contexto al serializador :
vistas.py
class UserRequestViewSet(APIView):
def get(self, request, pk=None, format=None):
user = ...
serializer_context = {
''request'': request,
}
serializer = api_serializers.UserSerializer(user, context=serializer_context)
return Response(serializer.data)
De esta manera, puede continuar usando la url en su serializador: serializers.py
...
url = serializers.HyperlinkedIdentityField(view_name="user")
...