You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改ModelViewSet的数据展示格式?实现分支机构按国家分组

按国家分组返回分支机构数据的实现方案

方法一:重写视图list方法,从分支机构数据分组

步骤1:创建城市数据序列化器

定义仅序列化分支机构核心字段的序列化器,无需嵌套国家信息:

class FilialCitySerializer(serializers.ModelSerializer):
    class Meta:
        model = Filials
        fields = ['name', 'subdomain_name', 'address']

步骤2:重写视图list方法

在原有FilialsViewSet中重写list方法,实现分组逻辑:

from django.http import Response
from itertools import groupby

class FilialsViewSet(viewsets.ModelViewSet):
    # 提前关联country并排序,避免N+1查询,同时保证groupby能正确分组
    queryset = Filials.objects.all().select_related('country').order_by('country__name')
    serializer_class = FilialsSerializer

    def list(self, request, *args, **kwargs):
        # 获取过滤后的查询集
        queryset = self.filter_queryset(self.get_queryset())
        
        # 按国家分组,生成目标格式数据
        response_data = []
        # 用country对象作为分组键,确保同一国家的分支机构被归为一组
        for country, filial_group in groupby(queryset, key=lambda x: x.country):
            # 序列化当前国家下的所有分支机构
            cities_data = FilialCitySerializer(filial_group, many=True).data
            response_data.append({
                "country": country.name,
                "cities": cities_data
            })
        
        return Response(response_data)

方法二:从国家模型出发,嵌套序列化分支机构

该方法更贴合分组后的逻辑结构,直接查询国家并关联下属分支机构:

步骤1:创建国家带分支机构的序列化器

class FilialCitySerializer(serializers.ModelSerializer):
    class Meta:
        model = Filials
        fields = ['name', 'subdomain_name', 'address']

class CountryWithFilialsSerializer(serializers.ModelSerializer):
    # 这里的source对应Filials模型中外键指向CountryFilials的反向关联名称,默认是`filials_set`,如果模型中设置了related_name则用对应值
    cities = FilialCitySerializer(source='filials_set', many=True)
    
    class Meta:
        model = CountryFilials
        fields = ['name', 'cities']

步骤2:调整视图的查询集和序列化器

from django.http import Response

class FilialsViewSet(viewsets.ModelViewSet):
    # 查询所有包含分支机构的国家,预加载下属分支机构避免N+1查询
    queryset = CountryFilials.objects.filter(filials__isnull=False).distinct().prefetch_related('filials_set')
    serializer_class = CountryWithFilialsSerializer

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        serializer = self.get_serializer(queryset, many=True)
        # 调整格式,把name字段重命名为country
        response_data = [
            {"country": item["name"], "cities": item["cities"]}
            for item in serializer.data
        ]
        return Response(response_data)

关键说明

  • 两种方法均使用select_related或prefetch_related避免数据库N+1查询问题,提升接口性能。
  • 若Filials模型中外键指向CountryFilials时设置了related_name(比如related_name='filials'),需将代码中的filials_set替换为对应的related_name值。

内容的提问来源于stack exchange,提问作者Pretty Cow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 20:41:06