如何使用 Django Rest Framework 为列表和详细信息视图设置不同的序列化程序?
Posted
技术标签:
【中文标题】如何使用 Django Rest Framework 为列表和详细信息视图设置不同的序列化程序?【英文标题】:How do I set different Serializer for list and detail view with Django Rest Framework? 【发布时间】:2014-09-08 16:34:27 【问题描述】:如何在使用viewsets.ModelViewSet
和HyperlinkedSerializer
时为列表和详细信息视图设置不同的序列化程序?
我通过定义list
和retrive
(here's an example) 了解如何使用viewsets.ViewSet
来实现它,但我不知道如何优雅地使其适应viewsets.ModelViewSet
【问题讨论】:
***.com/questions/22616973/… 【参考方案1】:我改编了来自“Django rest framework, use different serializers in the same ModelViewSet”的答案,对我很有帮助,希望对你有用:
class MyModelViewSet(viewsets.MyModelViewSet):
queryset = MyModel.objects.all()
serializer_class = MyModelListSerializer
detail_serializer_class = MyModelDetailSerializer
def get_serializer_class(self):
if self.action == 'retrieve':
if hasattr(self, 'detail_serializer_class'):
return self.detail_serializer_class
return super(MyModelViewSet, self).get_serializer_class()
在这种情况下,您只需指定两个序列化程序并根据操作使用一个。但是,这可以更通用(适用于所有操作),如下所示:
class MyModelViewSet(viewsets.MyModelViewSet):
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
action_serializers =
'retrieve': MyModelDetailSerializer,
'list': MyModelListSerializer,
'create': MyModelCreateSerializer
def get_serializer_class(self):
if hasattr(self, 'action_serializers'):
return self.action_serializers.get(self.action, self.serializer_class)
return super(MyModelViewSet, self).get_serializer_class()
【讨论】:
API 请求列表与详细信息有何不同? 它也非常适合我的用例。你能解释一下第二种方法吗?【参考方案2】:Viewsets 扩展了 GenericAPIView 类,因此您可以使用this part of the documentation 来解决您的问题。基本上,您需要重写 get_serializer_class 并根据您的请求返回不同的序列化程序。
【讨论】:
【参考方案3】:我为这项工作创建了这个小包。 drf_custom_viewsets。
它有CustomSerializerViewSet
,继承自ModelViewSet
,可以让你为不同的动作设置不同的序列化器。
【讨论】:
【参考方案4】:从 2021 年开始,我将采取不同的做法,一种更好、更通用的方法是这样做:
class PlayersListViewSet(viewsets.ModelViewSet):
queryset = Player.objects.all()
serializer_class = PlayersListSerializer
http_method_names = ['get', 'post']
pagination_class = None
filter_backends = [filters.OrderingFilter]
ordering_fields = ['name']
serializer_class_by_action =
'retrieve': PlayersDetailSerializer,
'list': PlayersListSerializer,
def get_serializer_class(self):
if hasattr(self, 'serializer_class_by_action'):
return self.serializer_class_by_action.get(self.action, self.serializer_class)
return super(MyModelViewSet, self).get_serializer_class()
def get_queryset(self):
queryset = Player.objects.all()
team_id = self.request.query_params.get('team', None)
if team_id:
try:
queryset = queryset.filter(team=team_id)
except ValueError:
raise exceptions.ParseError()
return queryset
这里action
是序列化器使用的方法,list
在def list
的情况下,retrieve
在def retrieve
的情况下等等..
【讨论】:
【参考方案5】:感谢@bbengfort,我提供了一个简单的解决方案,无需创建新的ViewSet
。
Django ViewSet 中每个操作的不同序列化器
TL;DR
在下面的代码中,我们基于Django documentation 覆盖get_serializer_class
,并且如果需要,我们会为每个操作指定不同的序列化程序:
Views.py
class TestAPIView(viewsets.ModelViewSet):
permission_classes = (IsAuthenticated,)
serializer_class = TestAPISerializer
serializer_class_by_action =
'update_me': UpdateMeSerializer,
def get_serializer_class(self):
if hasattr(self, 'serializer_class_by_action'):
return self.serializer_class_by_action.get(self.action, self.serializer_class)
return self.serializer_class
@action(detail=True, methods=['patch'], url_name='Update Me', url_path='updateme')
def update_me(self, request, pk=None):
# Write your own logic
return Response("OK")
Serializers.py
class UpdateMeSerializer(serializers.Serializer):
count = serializers.CharField(required=False, allow_null=True, default=10)
class Meta:
fields = ['count']
【讨论】:
以上是关于如何使用 Django Rest Framework 为列表和详细信息视图设置不同的序列化程序?的主要内容,如果未能解决你的问题,请参考以下文章
django.test.client 上的 Django rest 框架导入错误
无法使用 Django Rest 框架发送压缩的 gzip 数据
Django REST to React - 无需密码即可获取社交身份验证令牌
尽管有 AllowAny 权限,django-rest-framework 在 POST、PUT、DELETE 上返回 403 响应