如何在Django Rest Framework中序列化多表Join查询的结果集
方案1(推荐):使用Django ORM + DRF序列化器实现,无需原生SQL
首先假设你的模型定义符合以下关联规则:
from django.db import models class Country(models.Model): name = models.CharField(max_length=100) class State(models.Model): name = models.CharField(max_length=100) country = models.ForeignKey(Country, on_delete=models.CASCADE) class City(models.Model): name = models.CharField(max_length=100) state = models.ForeignKey(State, on_delete=models.CASCADE)
第一步:编写序列化器
直接通过source参数指定关联表字段,就能直接提取所需属性:
from rest_framework import serializers from .models import City class CityAutocompleteSerializer(serializers.ModelSerializer): state = serializers.CharField(source="state.name") country = serializers.CharField(source="state.country.name") class Meta: model = City fields = ["name", "state", "country"]
第二步:编写视图逻辑
用select_related提前完成连表查询,避免N+1性能问题,同时支持模糊匹配适配自动补全场景:
from rest_framework import generics from .models import City from .serializers import CityAutocompleteSerializer class CityAutocompleteView(generics.ListAPIView): serializer_class = CityAutocompleteSerializer def get_queryset(self): city_name = self.request.query_params.get("cityname", "") # 精确匹配用 name=city_name,模糊匹配用下面的icontains return City.objects.filter(name__icontains=city_name).select_related("state", "state__country")
返回的结果就是你需要的结构,列表中的每个元素都包含name、state、country三个字段,直接可以用于自动补全组件。
方案2:适配你提供的原生SQL查询方案
如果你坚持使用raw查询,只需编写普通Serializer匹配raw返回的字段别名即可:
from rest_framework import serializers class RawCitySerializer(serializers.Serializer): name = serializers.CharField(source="ci") state = serializers.CharField(source="s") country = serializers.CharField(source="co")
视图中直接传入raw查询的结果集即可,DRF可以正常序列化:
def get_queryset(self): city = self.request.query_params.get("cityname") return Cities.objects.raw("SELECT 1 as id, cities.name as ci, states.name as s, countries.name as co FROM cities JOIN states ON states.id = cities.state_id LEFT OUTER JOIN countries ON countries.id = states.country_id WHERE cities.name = %s", [city])
提示:更推荐方案1,Django ORM自带SQL注入防护,兼容不同数据库,后续维护成本远低于原生SQL。
内容的提问来源于stack exchange,提问作者ionecum
相关产品推荐
相关产品推荐

