你必须将东西分成视图和序列化器两部分。
序列化器
Serializer
是一个独立的对象。它用于将Django模型(或实际上任何类型的Python数据结构)转换为序列化形式,以及反过来。
无论何时需要,您都可以在任何地方使用它。只要您的输出不需要URI,它甚至不需要实际的HTTP请求。
ModelSerializer
子类是一种专门的Serializer
类型,它添加了“从模型加载”和“保存到模型”功能。
“保存到模型”入口点是save()
方法。为了更容易地进行重写,它的默认实现将其工作委托给序列化器的create()
或update()
方法,具体取决于它是创建新模型实例还是更新模型实例。
其目的是为了定制:它提供了开发人员选择仅覆盖创建方法、更新方法或通用行为的选项。
例如,它允许您执行以下操作:
def save(self, **kwargs):
kwargs['last_changed'] = timezone.now()
return super().save(**kwargs)
def create(self, instance, data):
data['initial_creation'] = timezone.now()
return super().create(instance, data)
这是一个基本的例子。在那里,last_changed
字段将在每次保存对象时被设置,无论是创建还是更新操作。
值得一提的是,您可能不希望这样做。像设置“last_changed”字段这样的事情应该存在于视图中,而不是序列化器中。
Viewsets
在完全不同的地方,Django REST framework 提供了 Viewsets
。这些是围绕实现模型的 CRUD API 的一组有组织的视图集合。
因此,它将其功能结构化为一组方法,即 create()
、retrieve()
/list()
、update()
和 delete()
。
主要的一点是:视图集的 create()
方法与序列化程序的 create()
方法之间没有任何关联。
只是恰好视图集的方法的默认实现使用了一个 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 的方法。
提示一下,你可以问自己以下问题:如果我在另一个地方使用相同的序列化程序(可能是另一个视图集),它是否应该始终显示该行为?