AssertionError:\`HyperlinkedIdentityField\` 需要序列化程序上下文中的请求

新手上路,请多包涵

我想创建一个 many-to-many 关系,一个人可以在多个俱乐部,一个俱乐部可以有很多人。我为以下逻辑添加了 models.pyserializers.py 但是当我尝试在命令提示符下序列化它时,出现以下错误 - 我在这里做错了什么?我什至没有 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)

检查创建的序列化器给了我这个 -

 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)

但是 serializer.data 给我错误

编辑

我意识到错误可能是因为 url 模式,所以我添加了以下 url 模式,但我仍然收到错误 -

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

原文由 qwertp 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 735
2 个回答

您收到此错误是因为 HyperlinkedIdentityField 期望在序列化程序的 context request 以便它可以构建绝对 URL。当您在命令行上初始化序列化程序时,您无权访问请求,因此会收到错误消息。

如果你需要在命令行上检查你的序列化器,你需要做这样的事情:

 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

您的 url 字段看起来像 http://testserver/person/1/

原文由 Ashley ‘CptLemming’ Wilson 发布,翻译遵循 CC BY-SA 3.0 许可协议

我有两个解决方案…

网址.py

1) 如果您使用的是 router.register,则可以添加 base_name

 router.register(r'users', views.UserViewSet, base_name='users')
urlpatterns = [
    url(r'', include(router.urls)),
]

2) 如果你有这样的事情:

 urlpatterns = [
    url(r'^user/$', views.UserRequestViewSet.as_view()),
]

您必须 将上下文传递给序列化程序

视图.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)

像这样你可以继续在你的序列化器上使用 url: serializers.py

 ...
url = serializers.HyperlinkedIdentityField(view_name="user")
...

原文由 Slipstream 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题