如何在Django REST Framework中将嵌套序列化数据转为单列表对象
Django REST Framework 实现嵌套数据扁平列表返回
当前代码采用嵌套序列化结构,返回国家包含州、州包含城市的层级数据,无法满足将每个(国家-州-城市)或(国家-州)组合作为独立条目返回的需求,以下是具体解决方案:
1. 修正模型笔误
先修复模型中的两处错误,避免后续运行报错:
class Country(models.Model): country_id = models.IntegerField(primary_key=True) cname = models.CharField(max_length=100) def __str__(self): return self.cname # 原代码误写为self.name,改为对应字段cname class City(models.Model): cityid= models.IntegerField(primary_key=True) city_name = models.CharField(max_length=100) city_strength = models.IntegerField() city_state = models.ForeignKey(State, related_name='cstate', on_delete=models.CASCADE) def __str__(self): return self.city_name # 原代码误写为self.sname,改为对应字段city_name
2. 定义扁平结构序列化器
不需要嵌套序列化器,直接创建包含所有所需字段的序列化器,允许城市相关字段为null(适配无城市的州):
from rest_framework import serializers from .models import Country, State, City class FlatLocationSerializer(serializers.Serializer): country_id = serializers.IntegerField() cname = serializers.CharField(max_length=100) stateid = serializers.IntegerField() state_name = serializers.CharField(max_length=100) cityid = serializers.IntegerField(allow_null=True) city_name = serializers.CharField(max_length=100, allow_null=True) city_strength = serializers.IntegerField(allow_null=True)
3. 调整视图生成扁平数据
在视图中根据国家ID获取关联数据,将每个关联组合转换为独立条目:
from rest_framework import generics, Response from django.db.models import Prefetch from .models import Country, State, City from .serializers import FlatLocationSerializer class FilterStateCityView(generics.ListAPIView): serializer_class = FlatLocationSerializer def get_queryset(self): # 从URL参数获取国家ID,示例请求URL:/locations/?country_id=23 country_id = self.request.query_params.get('country_id') if not country_id: return [] try: # 预关联数据避免N+1查询问题 country = Country.objects.prefetch_related( Prefetch('scountry', queryset=State.objects.prefetch_related('cstate')) ).get(country_id=country_id) except Country.DoesNotExist: return [] flat_data = [] # 遍历国家下的所有州 for state in country.scountry.all(): cities = state.cstate.all() if cities.exists(): # 每个城市生成一条独立记录 for city in cities: flat_data.append({ 'country_id': country.country_id, 'cname': country.cname, 'stateid': state.stateid, 'state_name': state.state_name, 'cityid': city.cityid, 'city_name': city.city_name, 'city_strength': city.city_strength }) else: # 无城市的州单独生成一条记录 flat_data.append({ 'country_id': country.country_id, 'cname': country.cname, 'stateid': state.stateid, 'state_name': state.state_name, 'cityid': None, 'city_name': None, 'city_strength': None }) return flat_data def list(self, request, *args, **kwargs): queryset = self.get_queryset() serializer = self.get_serializer(queryset, many=True) return Response(serializer.data)
预期响应示例
请求/locations/?country_id=23后,返回的响应格式如下:
[ { "country_id":23, "cname": "USA", "stateid": 16, "state_name": "Florida", "cityid":55, "city_name": "Miami", "city_strength": 40005 }, { "country_id":23, "cname": "USA", "stateid": 16, "state_name": "Florida", "cityid":56, "city_name": "Orlando", "city_strength": 930067 }, { "country_id":23, "cname": "USA", "stateid": 17, "state_name": "Texas", "cityid": null, "city_name": null, "city_strength": null } ]
内容的提问来源于stack exchange,提问作者Waseem
相关产品推荐
相关产品推荐

