为何DRF建议在序列化器中重写操作?与Viewsets中重写有何取舍?
DRF 序列化器与视图集重写方法的取舍逻辑
官方推荐在序列化器中重写方法的核心原因
- 职责分离原则:DRF 框架设计本身遵循单一职责划分,序列化器的核心定位是处理数据的校验、格式转换、数据持久化逻辑,视图集的核心定位是处理请求路由、权限校验、响应格式封装。把数据操作逻辑放在序列化器里,符合分层设计的要求,避免视图层变得臃肿。
- 逻辑复用:同一个序列化器可以被多个视图集、甚至是非视图的业务代码复用。例如你写的创建用户的逻辑放在
UserSerializer的create方法里,不管是后台管理的视图集、还是移动端注册的API视图,都可以直接调用,不需要在多个视图里重复写相同的创建逻辑。 - 校验与操作的强绑定:很多数据操作的逻辑和校验规则是强关联的,比如你要修改订单状态,首先要校验当前订单状态是否允许修改,这部分校验逻辑本身就写在序列化器里,把修改逻辑也放在序列化器的
update方法中,不需要把校验通过的数据再传给视图做二次处理,减少逻辑断层。
两类位置重写方法的优劣对比
在序列化器中重写create/update等方法
- 优势:
- 逻辑可复用性高,一处编写多处调用
- 和序列化校验逻辑天然衔接,不需要额外处理校验后的数据传递
- 便于做单元测试,不需要构造请求对象就可以直接对序列化器方法做测试
- 符合DRF的约定俗成,其他熟悉DRF的开发者可以快速定位到数据操作逻辑
- 劣势:
- 很难获取请求上下文的非数据参数,比如要根据请求用户的角色做不同的数据操作,需要额外把
request对象通过序列化器的context参数传进去,不如在视图里直接拿方便 - 不适合处理和请求强绑定的逻辑,比如多文件上传的解析、不同请求头对应的不同处理逻辑
- 很难获取请求上下文的非数据参数,比如要根据请求用户的角色做不同的数据操作,需要额外把
在视图集中重写create/update/destroy等方法
- 优势:
- 可以直接获取完整的请求上下文,包括请求用户、请求头、查询参数、上传文件等信息,处理和请求强关联的逻辑更简单
- 适合处理多模型关联的复杂操作,比如创建订单的同时要扣减库存、生成流水,这类跨域多个序列化器的逻辑放在视图里处理更清晰
- 可以更灵活的控制响应内容,比如不同权限的用户返回不同的响应字段,直接在视图里修改响应结构更方便
- 劣势:
- 逻辑复用性差,如果多个视图需要用到相同的操作逻辑,只能抽成公共函数或者继承公共父类,维护成本更高
- 很容易让视图代码变得臃肿,把校验、数据处理、响应处理的逻辑都堆在视图里,后期维护难度大
- 单元测试成本更高,需要构造完整的请求对象才能测试对应逻辑
实际开发的选择建议
如果你的逻辑核心是对单个模型的数据做校验和持久化,优先放在序列化器里重写;如果你的逻辑和请求上下文强绑定、需要处理多模型联动或者需要自定义响应结构,放在视图集里重写更合适。
内容的提问来源于stack exchange,提问作者Kishor Pawar
相关产品推荐
相关产品推荐

