qwertp qwertp - 5 months ago 31
Python Question

AssertionError: `HyperlinkedIdentityField` requires the request in the serializer context

I want to create a

many-to-many
relationship where one person can be in many clubs and one club can have many persons. I added the
models.py
and
serializers.py
for the following logic but when I try to serialize it in the command prompt, I get the following error - What am I doing wrong here? I don't even have a
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)


Inspecting the created serializer gives me this -

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)


but
serializer.data
gives me the error

******************edit*********************
I realized the error could be because of
url
patterns, so I added the following url patterns but I still get the 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'),
])

Answer

You're getting this error as the HyperlinkedIdentityField expects to receive request in context of the serializer so it can build absolute URLs. As you are initializing your serializer on the command line, you don't have access to request and so receive an error.

If you need to check your serializer on the command line, you'd need to do something like this:

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

Your url field would look something like http://testserver/person/1/.

Comments