您确实必须在视图和序列化器之间进行拆分。
序列化器
The Serializer
是一个独立的对象。它用于将 Django 模型(或实际上任何类型的 python 数据结构)转换为序列化形式,反之亦然。
您可以在任何您想要的地方使用它。只要输出中不需要 URI,它甚至不需要实际的 HTTP 请求。
The ModelSerializer
子类是一种特殊的类Serializer
添加了“从模型加载”和“保存到模型”功能。
“保存到模型”入口点是save()
方法。为了更容易覆盖,它的默认实现会将其工作委托给create()
or update()
序列化器的方法,具体取决于它是创建新的模型实例还是更新模型实例。
这样做的目的是定制:它为开发人员提供了仅覆盖创建方法、更新方法或常见行为的选项。
例如,它允许您执行以下操作:
def save(self, **kwargs):
# Will be done on every save
kwargs['last_changed'] = timezone.now()
return super().save(**kwargs)
def create(self, instance, data):
# Will only be done if a new object is being created
data['initial_creation'] = timezone.now()
return super().create(instance, data)
这是一个基本的例子。在那里,last_changed
每次保存对象时都会设置字段,无论是创建还是更新。
作为旁注,您可能不想这样做。诸如设置“last_changed”字段之类的内容应该存在于视图中,而不是序列化器中。
Viewsets
在完全不同的地方,Django REST 框架提供了Viewsets
。这些是有组织的视图集合,围绕为模型实现 CRUD API 展开。
因此,它将其功能构建为一组方法,即create()
, retrieve()
/list()
, update()
and delete()
.
要点是:视图集之间没有任何联系create()
方法和序列化器的create()
method.
碰巧视图集方法的默认实现使用了ModelSerializer
并且该序列化器的默认实现save()
方法将作业委托给具有相同名称的方法。
顺便说一句,关于last_changed
例如,以下是在视图中执行此操作的方法:
def perform_create(self, serializer):
now = timezone.now()
serializer.save(initial_creation=now, last_changed=now)
def perform_update(self, serializer):
serializer.save(last_changed=timezone.now())
这在功能上与上面的示例相同,但存在于视图集中。
结论
回到您的问题,您应该覆盖的具体内容取决于哪个对象负责您要添加的任务。
- 如果您的自定义行为是序列化过程的一部分,即将原始数据转换回正确的 Django 模型并保存它的过程,那么您应该覆盖
Serializer
的方法。
- 另一方面,如果您的自定义行为特定于您的视图集,那么您应该覆盖
Viewset
的方法。
作为提示,您可能会问自己以下问题:如果我在另一个地方(可能是另一个视图集)使用相同的序列化器,它是否应该始终显示该行为?