python - color - AssertionError: `HyperlinkedIdentityField` requiere la solicitud en el contexto del serializador




title in figure python (3)

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

Me encontré con el mismo problema. Mi enfoque es eliminar 'url' de Meta.fields en serializer.py.


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


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