color python django django-views django-rest-framework django-serializer

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") ...