【问题标题】:Representing more than single object/list CRUD ops with Django REST Framework ViewSets使用 Django REST 框架视图集表示多个对象/列表 CRUD 操作
【发布时间】:2016-05-15 12:14:38
【问题描述】:

我一直在用 Django 编写一个游戏选择风格的 webapp,最近决定用 DRF 将我的视图实现为 API 端点,以便在前端方法方面给我更多的灵活性。我的每个模型都有基本的序列化程序和视图集,我可以使用(优秀的)可浏览 API 正常浏览它们。以下是一对:

class SheetSerializer(serializers.HyperlinkedModelSerializer):
  user = UserSerializer(read_only = True)
  league = LeagueSerializer(read_only = True)
  picks = serializers.HyperlinkedRelatedField(
    source='pick_set',
    many=True,
    view_name='pick-detail',
    read_only = True
    )

  class Meta:
    model = Sheet
    fields = ('url', 'id', 'league_week', 'user', 'league', 'picks')

class GameSerializer(serializers.HyperlinkedModelSerializer):
  class Meta:
    model = Game
    fields = ('url', 'home_team', 'away_team', 'week', 'home_team_score', 'away_team_score')

class PickSerializer(serializers.HyperlinkedModelSerializer):
  sheet = SheetSerializer()
  game = GameSerializer()
  class Meta:
    model = Pick
    fields = ('url', 'sheet', 'amount', 'spread', 'pick_type', 'pick_team', 'game')

使用各自的视图集:

class PickViewset(viewsets.ModelViewSet):
  queryset = Pick.objects.all()
  serializer_class = PickSerializer

class GameViewset(viewsets.ModelViewSet):
  queryset = Game.objects.all()
  serializer_class = GameSerializer

class SheetViewset(viewsets.ModelViewSet):
  queryset = Sheet.objects.all()
  serializer_class = SheetSerializer

我目前遇到的问题是如何表示比单个对象或相同类型对象 CRUD 操作列表更复杂的端点。例如,我目前有一个用于匹配的常规 Django 视图,它会拉取用户表(选择集合)、另一个用户表,并显示嵌套的选择。我还计划在同一页面上显示来自他们所属联盟的其他用户的其他数据。 vanilla Django 中用户+对手数据的实现如下所示:

class MatchupDetail(DetailView):
  template_name = 'app/matchups.html'
  context_object_name = 'pick_sheet'

  def get_object(self):
    #logic to find and return object

  def get_opponent(self,username,schedule,week, **kwargs):
    #logic to find and return the opponent in the matchup

  def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    #logic to pull the opponents details and set them in the context

我一直在努力研究如何在 ViewSet 中表示它。使用常规的 Django 视图,很容易编写 get_object(或 get_list)以及 get_context_data,包括用户数据 + 来自数据库的任何其他所需对象,并将所有这些传递给模板。目前,上述(早期)API 端点版本如下所示:

class MatchupViewset(viewsets.ReadOnlyModelViewSet):
  serializer_class = SheetSerializer

  def get_queryset(self):
    user = self.request.user
    return Sheet.objects.filter(user=self.request.user)

  def list(self, request, format=None):
    sheets = self.get_queryset()
    serializer = SheetSerializer(sheets, many=True, context={'request': request})
    return Response(serializer.data)

  def retrieve(self, request, pk, format=None):
    sheet = Sheet.objects.get(user=self.request.user, league_week=pk)
    serializer = SheetSerializer(sheet, context={'request':request})
    return Response(serializer.data)

此代码有效,但仅返回有限的对象子集 - 单个用户工作表。我在这个 Viewset 中的目标是使用list() 返回给定联赛的所有比赛列表(只是用户表的集合),并使用retrieve() 给定联赛+周,但我不知道如何返回该数据。使用普通的 Django 上下文变量,您包含的额外数据可以以您喜欢的任何方式命名 - 使用 DRF 收集和返回任意数量的潜在不同对象的目标是如何实现的?编辑:这最初不是很清楚 - 我已经让嵌套表示工作,但我想知道是否有一种方法可以命名/标记不同的序列化对象,其方式是可以使用任何名称设置正常上下文中的信息

假设我想传递请求用户的序列化表格,以及他们的对手表格和所有其他球员表格,用于这个特定的联赛和一周。确定哪些属于用户,哪些属于他们的对手,哪些属于其他玩家的逻辑是否必须住在前端代码中?

另外,我将如何配置路由器以使 list() 方法始终需要 URL 参数(用于联赛)?每当我从

更改注册时
router.register(r'matchup', MatchupViewset, base_name = 'matchup') 

类似

router.register(r'matchup/(?P<league>[0-9]+)/$', MatchupViewset, base_name = 'matchup')

端点从可浏览的 API 根目录中消失。

【问题讨论】:

    标签: python django django-rest-framework


    【解决方案1】:

    使用 DRF 收集和返回任意数量的潜在不同对象的目标是如何实现的?

    我不确定这里的问题到底是什么。我假设您需要嵌套的表示,这在 here 中进行了解释。

    端点从可浏览的 API 根目录中消失。

    这是因为可浏览的 API 不知道如何解决额外的 kwargs。由于没有url匹配,他不会显示链接

    【讨论】:

    • 你说得对——我认为这个问题并不明确。我有嵌套表示工作,但我想知道是否有某种方法可以像使用 context 变量那样标记序列化对象的实例。关于 URL 问题:它不知道如何解决额外的参数是有道理的,我只是对如何指定它们是预期的感到困惑。由于路由器处理 Viewset URL,是否应该在 Viewset 中以某种方式指定额外的 URL?
    • 您可能需要查看github.com/alanjds/drf-nested-routers,尽管嵌套路由不被视为最佳做法。
    • 感谢您的链接!我很确定我以错误的方式思考路由器/URL 问题 - Viewsets 使很多事情变得简单,但我将重构以显式地将每个 Viewset 方法映射到具体视图,然后注册每个 URL手动。或者使用常规的基于 APIView 的类而不是 Viewsets,因为我似乎在这里遗漏了一些东西。再次感谢!
    猜你喜欢
    • 2015-08-04
    • 1970-01-01
    • 2017-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-21
    • 1970-01-01
    • 2023-04-08
    相关资源
    最近更新 更多