如何使用Django ORM实现表关联并生成DataTable兼容JSON响应
Django ORM关联查询+DataTable兼容JSON响应实现方案
问题背景
需要通过Django ORM实现Product与ProductCategory两张表的关联查询,返回兼容DataTable的JSON响应,要求包含产品详情及分类名称(categoryname)而非仅分类ID,现有模型、视图及Serializer代码已提供,但对Serializer的用法不熟悉。
解决方案
1. 修改ProductSerializer,添加分类名称字段
Serializer的核心作用是将Django模型对象转换为可直接序列化的Python字典,同时支持灵活扩展字段。我们需要在Serializer中新增自定义字段来获取关联分类的名称:
from rest_framework import serializers from .models import Product class ProductSerializer(serializers.ModelSerializer): # 自定义字段,从关联的category对象中提取categoryname categoryname = serializers.CharField(source='category.categoryname') class Meta: model = Product # 明确列出需要返回的所有字段,包含原产品字段及新增的categoryname fields = [ 'productid', 'sku', 'shortcode', 'category', 'categoryname', 'productname', 'description', 'barcode', 'treshhold', 'isactive' ]
source='category.categoryname':指定该字段的值来自Product实例关联的category(ProductCategory对象)的categoryname属性,序列化时会自动填充该值。
2. 调整视图代码,用Serializer替代model_to_dict
原代码中model_to_dict仅能提取模型自身字段,无法处理关联对象的自定义字段,改用Serializer完成序列化:
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.http import JsonResponse from .models import Product from .serializers import ProductSerializer def get_product(request): # 从请求参数中取值,添加默认值避免KeyError draw = int(request.GET.get('draw', 1)) start = int(request.GET.get('start', 0)) length = int(request.GET.get('length', 10)) sku_filter = request.GET.get('sku', '') # 使用select_related预加载关联的category,*避免N+1查询*,提升性能 products = Product.objects.filter(sku__icontains=sku_filter).select_related('category') recordsTotal = products.count() recordsFiltered = recordsTotal # 计算页码,使用整数除法避免浮点数问题 page = (start // length) + 1 paginator = Paginator(products, length) try: object_list = paginator.page(page) except PageNotAnInteger: object_list = paginator.page(1) except EmptyPage: object_list = paginator.page(paginator.num_pages) # 序列化分页后的产品列表,many=True表示处理多个对象 serializer = ProductSerializer(object_list, many=True) # serializer.data即为包含categoryname的目标字典列表 data = serializer.data json_res = { "draw": draw, "recordsTotal": recordsTotal, "recordsFiltered": recordsFiltered, 'data': data, } return JsonResponse(json_res)
request.GET.get():替代直接索引参数,避免前端未传参数时抛出KeyErrorselect_related('category'):预加载关联的分类数据,避免循环查询每个产品的分类(N+1问题)ProductSerializer(object_list, many=True):将分页后的产品列表批量序列化,自动处理每个产品的关联分类名称
3. Serializer核心工作原理
Serializer主要承担两种转换工作:
- 序列化:将Django模型实例转换为可直接生成JSON的Python字典,支持自定义字段、关联对象字段提取、数据格式化
- 反序列化:将前端传来的JSON数据转换为模型实例,同时完成数据验证
- 本次场景仅用到序列化功能,通过
source参数轻松关联获取关联表字段值
内容的提问来源于stack exchange,提问作者Vic Valdez
相关产品推荐
相关产品推荐

