迁移遗留API至DRF:序列化器文件整理最佳实践咨询
序列化器整理方案(不重构API前提下)
一、按模型拆分文件,告别大文件混乱
把原来的my_app/serializers.py拆成按模型分组的文件结构,每个模型对应一个序列化器文件:
my_app/ ├── serializers/ │ ├── __init__.py │ ├── template_serializers.py │ ├── color_serializers.py │ ├── font_serializers.py │ └── swatch_serializers.py
每个文件只放对应模型的所有序列化器版本,比如color_serializers.py里就放Color相关的列表、详情、嵌套用的序列化器。
- 可以在
__init__.py里按需导入常用序列化器,方便其他模块直接引用:from .template_serializers import TemplateListSerializer, TemplateDetailSerializer, TemplateCreateSerializer from .color_serializers import ColorNestedSerializer, ColorDetailSerializer
二、用基类抽公共逻辑,减少重复代码
同一模型的多个序列化器肯定有重复字段或逻辑,抽成基类继承就行:
比如Color的序列化器:
# color_serializers.py class ColorBaseSerializer(serializers.ModelSerializer): # 所有版本共享的字段、验证逻辑都放这 class Meta: model = Color fields = ("id", "name", "hex_code") # 嵌套在其他序列化器里用的版本,只读+关联字段 class ColorNestedSerializer(ColorBaseSerializer): swatch = SwatchSerializer(read_only=True) class Meta(ColorBaseSerializer.Meta): fields = ColorBaseSerializer.Meta.fields + ("swatch",) # 独立详情接口用的版本,包含完整字段 class ColorDetailSerializer(ColorBaseSerializer): swatch = SwatchSerializer() class Meta(ColorBaseSerializer.Meta): fields = ColorBaseSerializer.Meta.fields + ("swatch", "description")
Template同理,把公共字段property_ids放到基类,其他版本继承后只加自己需要的字段:
# template_serializers.py class TemplateBaseSerializer(serializers.ModelSerializer): property_ids = serializers.PrimaryKeyRelatedField(many=True, queryset=Property.objects.all()) class Meta: model = Template fields = ("id", "name", "property_ids") # 列表视图用,只返回基础字段 class TemplateListSerializer(TemplateBaseSerializer): pass # 详情视图用,嵌套完整关联数据 class TemplateDetailSerializer(TemplateBaseSerializer): colors = ColorNestedSerializer(read_only=True, many=True) fonts = FontNestedSerializer(read_only=True, many=True) class Meta(TemplateBaseSerializer.Meta): fields = TemplateBaseSerializer.Meta.fields + ("colors", "fonts") # 创建用,只保留可写字段 class TemplateCreateSerializer(TemplateBaseSerializer): class Meta(TemplateBaseSerializer.Meta): fields = TemplateBaseSerializer.Meta.fields
三、统一命名规范,一眼看懂用途
给序列化器起直观的名字,用后缀区分使用场景:
List:列表视图专用,比如TemplateListSerializerDetail:详情视图专用,比如ColorDetailSerializerCreate/Update:创建/更新动作专用,比如TemplateCreateSerializerNested:嵌套在其他序列化器里用,比如ColorNestedSerializer
这样不用看代码,光看名字就知道序列化器是干啥的。
四、ViewSet里明确映射序列化器,逻辑清晰
不用写一堆if判断,直接用字典按动作映射序列化器:
class TemplateViewSet(viewsets.ModelViewSet): queryset = Template.objects.all() serializer_classes = { "list": TemplateListSerializer, "retrieve": TemplateDetailSerializer, "create": TemplateCreateSerializer, "update": TemplateUpdateSerializer, "partial_update": TemplatePartialUpdateSerializer, } def get_serializer_class(self): return self.serializer_classes[self.action]
如果多个ViewSet都要这么用,把get_serializer_class抽成基类ViewSet,其他ViewSet继承就行:
class BaseActionSerializerViewSet(viewsets.ModelViewSet): serializer_classes = {} def get_serializer_class(self): return self.serializer_classes[self.action] # 之后的ViewSet直接继承这个基类 class TemplateViewSet(BaseActionSerializerViewSet): queryset = Template.objects.all() serializer_classes = { "list": TemplateListSerializer, # ... 其他动作对应的序列化器 }
五、严格区分嵌套和独立用的序列化器
像Color这种既要嵌套在其他序列化器里,又有独立API接口的,分开写两个序列化器:
ColorNestedSerializer:只读,只包含嵌套场景需要的字段,避免冗余ColorDetailSerializer:独立接口用,包含完整字段,支持读写(如果需要)
这样不会出现同一个序列化器在不同场景下的冲突,维护起来也方便
内容的提问来源于stack exchange,提问作者d-dev
相关产品推荐
相关产品推荐

