如何在Django Rest Framework中排除嵌套序列化器的指定字段?
解决方案
DRF 支持动态调整序列化器的字段列表,针对你的场景有两种成熟的实现方式:
方案1:重写序列化器初始化方法,动态排除字段(灵活度最高)
通过自定义初始化参数控制要排除的字段,同一个序列化器可以适配多场景使用:
class AmountSerializer(serializers.ModelSerializer): ingredient_name= serializers.ReadOnlyField(source='ingredient_name.name') # 正常定义meal_name字段 meal_name = serializers.ReadOnlyField(source='meal.name') class Meta: model = IngredientAmount fields = ('ingredient_name','amount','meal_name') def __init__(self, *args, **kwargs): # 取出自定义的排除字段参数 exclude_fields = kwargs.pop('exclude_fields', None) super().__init__(*args, **kwargs) # 存在排除字段时,从字段列表中删除 if exclude_fields: for field_name in exclude_fields: self.fields.pop(field_name, None)
嵌套使用时传入排除参数即可:
class MealSerializer(serializers.ModelSerializer): type_name= serializers.ReadOnlyField(source='type.name') ingredients = serializers.SlugRelatedField(read_only=True, slug_field='name', many=True) # 嵌套时指定排除meal_name字段 amount = AmountSerializer(read_only=True, many=True, source='meal_id', exclude_fields=['meal_name']) class Meta: model = Meal fields = ('id', 'name', 'type_name', 'recipe', 'photo', 'ingredients','amount')
使用效果:独立接口直接用AmountSerializer时meal_name正常返回,嵌套场景下自动隐藏该字段。
方案2:拆分序列化器(逻辑最清晰,无黑魔法)
如果字段规则固定,可以拆分基础序列化器和扩展序列化器,分别对应不同使用场景:
# 基础版本,不带meal_name,给嵌套场景使用 class BaseAmountSerializer(serializers.ModelSerializer): ingredient_name= serializers.ReadOnlyField(source='ingredient_name.name') class Meta: model = IngredientAmount fields = ('ingredient_name','amount') # 扩展版本,带meal_name,给独立ViewSet接口使用 class AmountSerializer(BaseAmountSerializer): meal_name = serializers.ReadOnlyField(source='meal.name') class Meta(BaseAmountSerializer.Meta): fields = BaseAmountSerializer.Meta.fields + ('meal_name',)
嵌套时直接使用基础版本即可:
amount = BaseAmountSerializer(read_only=True, many=True,source='meal_id')
补充说明
你之前尝试write_only=True不生效是因为该参数是全局禁止字段返回,不符合「部分场景返回、部分场景隐藏」的需求,上述两种方案都可以完美适配你的要求。
内容的提问来源于stack exchange,提问作者non
相关产品推荐
相关产品推荐

