如何在Django Rest Framework中设计食材ArrayField及对应序列化方法
解决方案
一、模型层字段定义
分两种实现方案,可根据业务需求选择:
方案1:JSONField直接存储(无单独食材管理需求优先选)
如果不需要对食材做独立的查询、统计、复用操作,直接用Django原生JSONField存储即可,代码最简:
from django.db import models class Meal(models.Model): name = models.TextField() recipe = models.TextField() # 直接存储嵌套数组结构,默认值设为空数组 ingredients = models.JSONField(default=list)
注:Django 3.1及以上版本原生支持JSONField,兼容PostgreSQL、MySQL、SQLite等主流数据库,会自动完成Python数据类型和数据库JSON格式的双向转换。
写入数据的示例:
Meal.objects.create( name="spaghetti", recipe="recipe", ingredients=[ [{"name":"pasta", "amount":100}, {"name":"tomato", "amount":200}] ] )
方案2:关联独立Ingredient模型(需要食材统一管理优先选)
如果后续需要统计食材使用频次、复用食材基础信息等,建议拆分独立模型做关联:
from django.db import models class Meal(models.Model): name = models.TextField() recipe = models.TextField() # 食材独立模型 class Ingredient(models.Model): name = models.TextField() amount = models.IntegerField() # 分组字段:用来匹配你需要的内层数组分组逻辑,没有分组需求可以删除 group = models.IntegerField(default=0) meal = models.ForeignKey(Meal, on_delete=models.CASCADE, related_name="ingredients")
二、序列化逻辑实现
和上面的两种方案一一对应:
对应方案1的序列化
不需要额外自定义逻辑,直接声明字段即可:
from rest_framework import serializers from .models import Meal class MealSerializer(serializers.ModelSerializer): class Meta: model = Meal fields = ["id", "name", "recipe", "ingredients"]
序列化后返回的结构和你存储的结构完全一致,直接匹配你给出的JSON格式要求。
对应方案2的序列化
需要自定义字段逻辑,把关联的食材对象按分组组装为嵌套数组:
from rest_framework import serializers from .models import Meal, Ingredient class IngredientSerializer(serializers.ModelSerializer): class Meta: model = Ingredient fields = ["name", "amount"] class MealSerializer(serializers.ModelSerializer): ingredients = serializers.SerializerMethodField() def get_ingredients(self, obj): # 按group字段分组 groups = {} for ing in obj.ingredients.all().order_by("group", "id"): groups.setdefault(ing.group, []).append(IngredientSerializer(ing).data) # 转换为嵌套数组返回 return list(groups.values()) class Meta: model = Meal fields = ["id", "name", "recipe", "ingredients"]
注:如果你给出的JSON中两层数组是笔误,只需要单层数组的话,直接把
ingredients字段声明为ingredients = IngredientSerializer(many=True)即可,不需要自定义get_ingredients方法。
内容的提问来源于stack exchange,提问作者non
相关产品推荐
相关产品推荐

