'list' (players/) 和 'detail' (players/{id}) 如何得到不同的结果?

How to have different results for 'list' (players/) and 'detail' (players/{id})?

情况是这样的。我在我的 Django REST API 上得到了一个列表:/playerslist/

它 returns 我是这样的球员名单:

http://pastebin.com/JYA39gHT

这正是我目前想要的。但是现在,我需要这个:

Going for /playerslist/1/ 给了我1号玩家的不同信息。这里的列表只是为了列出玩家的基本信息。但我需要播放器的详细视图,包含来自其他模型的信息和不同的序列化,这一定是一个基本问题,但由于我对 Django 和 Python 完全陌生,一般来说,我一定误解了一些东西。

这是我的视图集:

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

   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

我怎样才能做到这一点?我必须使用 @detail_route 才能得到类似 playerslist/1/detail 的东西吗?我已经尝试过了,但 DRF 的文档只显示了一个示例,对我来说根本不清楚。

要在执行 'detail' 视图时获得不同的结果,您需要在执行 'retrieve' 调用时更改序列化程序。我已经使用 ModelViewSet 的自定义 mixin 完成了此操作,它需要一个特殊的 "detail_serializer_class":

class DifferentDetailSerializerMixin(object):
  """
  For a viewset, mix this in to use a different serializer class
  for individual 'retrieve' views, different from the standard 
  serializer for lists.
  """
  def retrieve(self, request, *args, **kwargs):
      instance = self.get_object()
      serializer = self.detail_serializer_class(instance, context=self.get_serializer_context())
      return Response(serializer.data)

您的视图集很简单:

class PlayersListViewSet(DifferentDetailSerializerMixin, viewsets.ModelViewSet):
    queryset = Player.objects.all()
    serializer_class = PlayersListSerializer
    detail_serializer_class = PlayersDetailSerializer
    filter_backends = [filters.OrderingFilter]
    ordering_fields = ['name']

在这里,PlayersDetailSerializer 是另一个序列化程序,它有更多您想要 return 的字段。

顺便说一句,如果你想支持团队的可选过滤,我强烈建议使用 django-filter。这样您就不必担心验证等问题。安装后,只需将其添加到您的视图集中即可:

filter_backends = (filters.OrderingFilter, filters.DjangoFilterBackend, )
filter_fields = ['team']

有关详细信息,请参阅 the docs

您可以覆盖方法 retrieve(返回一个实例)或 list(显然返回列表),如 http://www.django-rest-framework.org/api-guide/viewsets/ 中的第一个示例所示。

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

   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

   def retrieve(self, request, *args, **kwargs):
       instance = self.get_object()
       serializer = PlayerDetailSerializer(instance)
       return Response(serializer.data)

其中 PlayerDetailSerializer 是另一个具有不同字段(任何你需要的)的序列化器,不需要在 serializer_class 中指定它。