如何通过Django高效将非规范化数据转换为JSON?
高效生成嵌套JSON的Django方案
针对你遇到的性能问题,不需要逐条检查商店/货架的存在性,以下几种方法可以大幅提升效率,直接生成目标JSON格式:
方法1:ORM排序 + itertools.groupby(最通用,性能优异)
先通过Django ORM将数据按store_id、shelf_id排序(groupby依赖有序数据集),再用Python标准库的itertools.groupby做层级分组,全程线性遍历,时间复杂度为O(n):
from itertools import groupby import json # 从数据库获取有序的扁平化数据 flat_data = YourModel.objects.values( 'store_id', 'shelf_id', 'product_id', 'qty' ).order_by('store_id', 'shelf_id') result = [] # 按商店分组 for store_id, shelf_groups in groupby(flat_data, key=lambda x: x['store_id']): store_entry = {store_id: []} # 按货架分组 for shelf_id, product_groups in groupby(shelf_groups, key=lambda x: x['shelf_id']): shelf_entry = {shelf_id: []} # 生成产品条目 for item in product_groups: shelf_entry[shelf_id].append({item['product_id']: item['qty']}) store_entry[store_id].append(shelf_entry) result.append(store_entry) # 转换为JSON target_json = json.dumps(result)
性能优势:
- 数据库层面的排序比Python内存排序快数倍,
groupby仅需一次线性遍历 - 完全消除原方案中每条记录都要做的字典键存在性检查,避免了O(n²)的时间开销
方法2:嵌套序列化器(适合有模型关联的场景)
如果你的Store、Shelf、Product模型已经通过外键建立层级关联(比如Shelf关联Store,Product关联Shelf),可以用Django REST Framework的嵌套序列化器直接生成目标结构,同时用prefetch_related避免N+1查询:
from rest_framework import serializers from django.db.models import Prefetch class ProductSerializer(serializers.ModelSerializer): def to_representation(self, instance): # 自定义产品输出格式 return {instance.product_id: instance.qty} class ShelfSerializer(serializers.ModelSerializer): products = ProductSerializer(many=True, source='product_set') def to_representation(self, instance): # 自定义货架输出格式 return {instance.shelf_id: self.fields['products'].to_representation(instance)} class StoreSerializer(serializers.ModelSerializer): shelves = ShelfSerializer(many=True, source='shelf_set') def to_representation(self, instance): # 自定义商店输出格式 return {instance.store_id: self.fields['shelves'].to_representation(instance)} # 预加载所有关联数据,避免多次数据库查询 stores = Store.objects.prefetch_related( Prefetch('shelf_set', queryset=Shelf.objects.prefetch_related('product_set')) ) # 直接生成目标JSON结构 target_data = StoreSerializer(stores, many=True).data
方法3:原生SQL聚合(超大数据量场景)
如果数据量达到千万级,可直接用数据库的JSON聚合函数完成大部分工作,大幅降低Python端的内存占用:
from django.db import connection import json with connection.cursor() as cursor: # 数据库层面按商店、货架分组,聚合产品为JSON数组 cursor.execute(""" SELECT store_id, shelf_id, json_agg(json_build_object(product_id, qty)) AS products FROM your_table_name GROUP BY store_id, shelf_id ORDER BY store_id, shelf_id """) shelf_level_data = cursor.fetchall() # 最后按商店分组整合结果 result = [] for store_id, shelf_groups in groupby(shelf_level_data, key=lambda x: x[0]): store_entry = {store_id: []} for shelf_id, products in shelf_groups: store_entry[store_id].append({shelf_id: json.loads(products)}) result.append(store_entry)
内容的提问来源于stack exchange,提问作者user1933205
相关产品推荐
相关产品推荐

