何时在djangorestframework序列化器中调用创建和更新?

时间:2015-05-23 05:05:24

标签: python django django-rest-framework

我目前正在为我的应用RESTful API实施djangorestframework。在使用它之后,我仍然不清楚.create(self, validated_data).update(self, validated_data)在序列化程序中使用了什么。据我了解, CRUD 仅调用viewsets.ModelViewSet中的4种主要方法:create()retrive()update()destroy()

我还尝试过调试和打印内容,以了解.create().update()中何时调用ModelViewSetModelSerializer方法。显然,当我执行HTTP动词时,只调用ModelViewSet中的方法。但是,对于ModelSerializer,我在这两种方法中看不到任何调用。我只是想知道ModelSerializer中使用的那些方法是什么,因为我发现人们在序列化器中大量重写这些方法。

P / S:我是djangorestframework的新手,对不起我的英语,因为我不是本地人。

谢谢:)

3 个答案:

答案 0 :(得分:59)

你真的必须在视图和序列化器之间拆分。

串行器

Serializer是一个独立的对象。它用于将Django模型(或任何类型的python数据结构,实际上)转换为序列化形式,反之亦然。 您可以随意使用它。只要您的输出中不需要URI,它甚至不需要实际的HTTP请求。

ModelSerializer子类是一种特殊类型的Serializer,它添加了“从模型加载”和“保存到模型”功能。 “保存到模型”入口点是save()方法。为了更容易覆盖,它的默认实现会将其工作委托给序列化程序的create()update()方法,具体取决于它是创建新模型实例还是更新模型实例。

这样做的目的是自定义:它为开发人员提供了仅覆盖create方法,更新方法或常见行为的选项。 例如,它允许您执行此类操作:

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()delete()

主要观点是:视图集的create()方法与序列化程序的create()方法之间没有任何关联。

恰好,viewset方法的默认实现使用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的方法。

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

答案 1 :(得分:14)

我终于了解.create().update()如何在Serializer中工作(特别是ModelSerializer)以及它们如何与Viewsets相关联(尤其是{{1} }})。如果有人提出这个问题,我只想更清楚地澄清这个概念。

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

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

答案 2 :(得分:3)

在rest-api设计中,创建,读取,更新和删除是标准。 创建和更新没有太大的区别。

请参阅this

请参阅create()方法将创建一个项目。

update()方法需要指定要更新的项目。