Python 用Django REST Framework视图集表示多个对象/列表CRUD操作

Python 用Django REST Framework视图集表示多个对象/列表CRUD操作,python,django,django-rest-framework,Python,Django,Django Rest Framework,我一直在用Django编写一个游戏挑选风格的webapp,最近决定用DRF将我的视图实现为API端点,以便在涉及前端方法时给我更多的灵活性。我的每个模型都有基本的序列化程序和视图集,我可以使用(优秀的)可浏览API正常浏览它们。以下是几点: class SheetSerializer(serializers.HyperlinkedModelSerializer): user = UserSerializer(read_only = True) league = LeagueSeriali

我一直在用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
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)
我一直在努力研究如何在视图集中表示这一点。使用常规的Django视图,很容易编写get_对象(或get_列表)以及get_context_数据,包括用户数据和数据库中任何其他所需对象,并将所有这些传递给模板。目前,上述的(早期)API端点版本如下所示:

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
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)
这段代码可以工作,但只返回有限的对象子集-单个用户表。我在这个视图集中的目标是返回一个列表,其中列出了
list()。使用普通的Django上下文变量,您包含的额外数据可以以您喜欢的任何方式命名-使用DRF收集和返回任意数量的潜在不同对象的目标是如何实现的?编辑:这一点一开始不是很清楚-我已经使用了嵌套表示,但我想知道是否有一种方法可以命名/标记不同的序列化对象,使正常上下文中的信息可以用任何名称设置

假设我想通过请求用户的序列表,以及他们的对手表和这个特定联赛和本周的所有其他球员表。逻辑会决定哪些属于用户,哪些属于他们的对手,哪些是其他玩家必须生活在前端代码中吗

另外,如何配置路由器,使list()方法始终需要URL参数(用于联盟)?任何时候我从

router.register(r'matchup', MatchupViewset, base_name = 'matchup') 
差不多

router.register(r'matchup/(?P<league>[0-9]+)/$', MatchupViewset, base_name = 'matchup')
router.register(r'matchup/(?P[0-9]+)/$),MatchupViewset,base_name='matchup')
端点将从可浏览的API根目录中消失

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

我不确定这里到底是什么问题。我想你会想要嵌套的表示,这是解释过的

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


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

你是对的-我认为这个问题不清楚。我有嵌套表示,但我想知道是否有某种方法可以像使用
上下文
变量那样标记序列化对象的实例。关于URL问题:它不知道如何解析额外的参数是有道理的,我只是不知道如何指定它们是预期的。由于路由器处理视图集URL,是否应该以某种方式在视图集中指定一个额外的URL?尽管嵌套路由不被视为最佳做法,但您可能希望了解这一点。感谢链接!我很确定我对路由器/URL问题的想法是错误的——视图集使很多事情变得简单,但我将进行重构,将每个视图集方法显式地映射到一个具体的视图,然后手动注册每个URL。或者使用常规的基于APIView的类而不是视图集,因为这里似乎缺少一些东西。再次感谢!