Skip to main content
 首页 » 编程设计

python之使用 Django REST Framework ViewSets 表示多个对象/列表 CRUD 操作

2025年05月04日36jirigala

我一直在用 Django 编写一个游戏选择风格的网络应用程序,最近决定用 DRF 将我的 View 实现为 API 端点,以便在前端方法方面给我更大的灵 active 。我的每个模型都有基本的序列化程序和 ViewSet,我可以使用(优秀的)可浏览 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') 

使用相应的 ViewSets:

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 View ,它拉取用户表(Picks 的集合)、另一个用户表,并相互显示嵌套的 Picks。我还计划在同一页面上显示其他用户在他们所属的任何联盟中的其他数据。 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 View ,很容易编写 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 完成收集和返回任意数量的潜在不同对象的目标?编辑:最初这不是很清楚-我已经得到嵌套表示工作,但我想知道是否有一种方法来命名/标记不同的序列化对象,以便在正常上下文中可以使用任何名称设置信息

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

此外,我该如何配置路由器,以便 list() 方法始终需要一个 URL 参数(对于联赛)?任何时候我从

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

类似于

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

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

请您参考如下方法:

how is the goal of collecting and returning an arbitrary number of potentially different objects accomplished with DRF?

我不确定这里的问题到底是什么。我假设您需要嵌套表示 here .

the endpoint disappears from the browsable API root.

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