AssertionError: `HyperlinkedIdentityField` requires the request in the serializer context
AssertionError: `HyperlinkedIdentityField` requires the request in the serializer context
我想建立一个 many-to-many
关系,一个人可以在多个俱乐部,一个俱乐部可以有很多人。我为以下逻辑添加了 models.py
和 serializers.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
给我错误
Edit
我意识到错误可能是因为 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'),
])
您收到此错误是因为 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/
。
我遇到了同样的问题。我的方法是从 serializer.py 中的 Meta.fields 中删除 'url'。
我有两个解决方案...
urls.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()),
]
您必须将上下文传递给序列化程序:
views.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 的回答,我编辑了我的 views.py
介绍上下文,现在它起作用了。
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)
根据MDT的回复,我使用了django-rest-framework,将request改成request._request解决了。
serializer_context = {'request': Request(request._request)}
您可以简单地通过将实例化(在 views.py 中)更改为这样的事情来解决它:
your_serializer = YourModelSerializer(YourQuerySet_or_object, many=True,context={'request':request})
在您只需要相对 URL 的情况下,您可以简单地将 None
传递给 'request'
中的 context
键,例如;在命令行中测试序列化程序。
serializer = YourModelSerializer(modelInstance_or_obj, context={'request': None})
对于外部网址,您只需将请求放在 None:
context={
'request': None
},
在我的例子中,我不得不将字段名称从 url 更改为任何其他名称。讨厌自动魔法
我想建立一个 many-to-many
关系,一个人可以在多个俱乐部,一个俱乐部可以有很多人。我为以下逻辑添加了 models.py
和 serializers.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
给我错误
Edit
我意识到错误可能是因为 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'),
])
您收到此错误是因为 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/
。
我遇到了同样的问题。我的方法是从 serializer.py 中的 Meta.fields 中删除 'url'。
我有两个解决方案...
urls.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()),
]
您必须将上下文传递给序列化程序:
views.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 的回答,我编辑了我的 views.py
介绍上下文,现在它起作用了。
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)
根据MDT的回复,我使用了django-rest-framework,将request改成request._request解决了。
serializer_context = {'request': Request(request._request)}
您可以简单地通过将实例化(在 views.py 中)更改为这样的事情来解决它:
your_serializer = YourModelSerializer(YourQuerySet_or_object, many=True,context={'request':request})
在您只需要相对 URL 的情况下,您可以简单地将 None
传递给 'request'
中的 context
键,例如;在命令行中测试序列化程序。
serializer = YourModelSerializer(modelInstance_or_obj, context={'request': None})
对于外部网址,您只需将请求放在 None:
context={
'request': None
},
在我的例子中,我不得不将字段名称从 url 更改为任何其他名称。讨厌自动魔法