python - 什么时候在 django rest 框架序列化程序中调用创建和更新?

标签 python django django-rest-framework

我目前正在为我的应用程序 RESTful API 实现 djangorestframework。玩了之后,我还是不太明白序列化器中 .create(self,validated_data).update(self,validated_data) 是干什么用的。据我了解,CRUD 只调用 viewsets.ModelViewSet 中的 4 个主要方法:create()retrive()update()destroy()

我也已经尝试调试并打印出一些东西,看看何时在 ModelViewSet 中调用了 .create().update() 方法ModelSerializer。显然,当我执行 HTTP 动词时,只调用了 ModelViewSet 中的方法。但是,对于 ModelSerializer,我在这两种方法中看不到任何调用。我只是想知道 ModelSerializer 中使用的那些方法是什么,因为我看到人们在序列化器中重写了很多方法。

最佳答案

您确实必须在 View 和序列化程序之间进行拆分。

序列化器

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

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

这样做的目的是自定义:它为您(开发人员)提供了仅覆盖 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”字段之类的东西应该存在于 View 中,而不是序列化器中。

View 集

在一个完全不同的地方,Django REST 框架提供 Viewsets。这些是有组织的 View 集合,围绕着为模型实现 CRUD API。 因此,它将其功能构造为一组方法,即 create()retrieve()/list() update()delete().

重点是: View 集的 create() 方法和序列化程序的 create() 方法之间没有任何联系。

恰好 View 集方法的默认实现使用 ModelSerializer 并且该序列化器的 save() 方法的默认实现将作业委托(delegate)给具有同名。

顺便说一下,关于 last_changed 示例,您可以在 View 中执行以下操作:

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

这在功能上等同于上面的示例,但存在于 View 集中。

结论

回到您的问题,您应该覆盖的具体内容取决于哪个对象负责您要添加的任务。

  • 如果您的自定义行为是序列化过程的一部分,即将原始数据转换回适当的 Django 模型并保存它的过程,那么您应该重写 Serializer 的方法。
  • 另一方面,如果您的自定义行为特定于您的 View 集,那么您应该覆盖 Viewset 的方法。

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

关于python - 什么时候在 django rest 框架序列化程序中调用创建和更新?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30409076/

相关文章:

json - 如何使用 django Rest 框架修改多对多集合

python - 上传 PyPi 包报错

django - Django 模板系统中的 bool 逻辑

python - 如何使用 Django 比较要使用 Markdown 渲染的两个模型?

python - Django ModelMultipleChoiceField 对象没有属性 to_field_name

Django REST 框架 APIClient 在 shell 中进行身份验证,但不在我的单元测试中

python - celery worker 不工作虽然 rabbitmq 有队列建立

python - 使用cookiecutter捕获eval()SyntaxError的问题

python - 在 bash 中运行 python 脚本时出现无效语法错误

django - 在 VueJS 中存储身份验证 token 的最佳实践?