Django REST framework序列化器中的create和update方法何时被调用?

34

我正在为我的应用程序的RESTful API实现djangorestframework。在尝试了一些东西之后,我仍然不清楚序列化器中的.create(self, validated_data).update(self, validated_data)用途是什么。据我所知,CRUD只调用viewsets.ModelViewSet中的4个主要方法:create()retrieve()update()destroy()

我已经尝试过调试并打印出一些内容,以查看在序列化器中何时调用.create().update()方法以及在ModelViewSet中何时调用这些方法。显然,当我执行HTTP动词时,只有ModelViewSet中的方法被调用。然而,在ModelSerializer中,我没有看到任何对这两个方法的调用。我只想知道在ModelSerializer中这些方法的作用,因为我发现人们经常在序列化器中重写这些方法。

3个回答

83

你必须将东西分成视图和序列化器两部分。

序列化器

Serializer是一个独立的对象。它用于将Django模型(或实际上任何类型的Python数据结构)转换为序列化形式,以及反过来。 无论何时需要,您都可以在任何地方使用它。只要您的输出不需要URI,它甚至不需要实际的HTTP请求。

ModelSerializer子类是一种专门的Serializer类型,它添加了“从模型加载”和“保存到模型”功能。 “保存到模型”入口点是save()方法。为了更容易地进行重写,它的默认实现将其工作委托给序列化器的create()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 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 的方法。

提示一下,你可以问自己以下问题:如果我在另一个地方使用相同的序列化程序(可能是另一个视图集),它是否应该始终显示该行为?


2
谢谢你的回答!非常详细深入,正是我想要的。+1 :) - Tim

21

我终于理解了在Serializer(特别是ModelSerializer)中如何使用.create().update(),以及它们如何与Viewsets(特别是ModelViewSet)相连接。如果有人来问这个问题,我只想更清楚地澄清这个概念。

基本上,在ModelViewSet中,CRUD的4种方法:.create().retrieve().update().destroy()将处理来自HTTP动词的调用。默认情况下,ModelViewSet中的.create().update()将通过调用BaseSerializer类的.save()方法来调用ModelSerializer中的.create().update()

然后,save()方法将通过确定对象self.instance是否存在来确定它是否会在ModelSerializer中调用.create().update()


2
在REST API设计中,创建(create)、读取(read)、更新(update)和删除(delete)是标准操作。在创建和更新中没有太大的区别。
请参考以下链接:此链接
查看create()方法将创建一个项目。
以及 update()方法需要指定要更新的项目。

这两者之间有什么区别? - Tim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接