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

Tim*_*Tim 25 python django django-rest-framework

我目前正在为我的应用RESTful API实现djangorestframework.玩弄之后,我仍然不清晰了解项目.create(self, validated_data).update(self, validated_data)用于串行.据我了解,CRUD只要求在4种主要方法viewsets.ModelViewSet:create(),retrive(),update(),和destroy().

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

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

谢谢 :)

spe*_*ras 62

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

串行器

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)
Run Code Online (Sandbox Code Playgroud)

这是一个基本的例子.在那里,last_changed每次保存对象时都会设置该字段,无论是创建还是更新.作为旁注,您可能不想这样做.设置"last_changed"字段等内容应该在视图中,而不是在序列化程序中.

Viewsets

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

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

恰好,viewset的方法ModelSerializer的默认实现使用了a,并且该序列化程序的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())
Run Code Online (Sandbox Code Playgroud)

这在功能上等同于上面的示例,但它位于视图集中.

结论

回到你的问题,你应该覆盖的具体事情取决于哪个对象负责你想要添加的任务.

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

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

  • 谢谢你的回答!它非常详细和深入,就像我想要的那样。+1 :) (2认同)

Tim*_*Tim 14

我终于明白是怎么.create().update()工作Serializer(尤其是ModelSerializer)以及它们是如何连接到Viewsets(尤其是ModelViewSet).如果有人提出这个问题,我只想更清楚地澄清这个概念.

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

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