问题 Django REST Framework,pre_save()和serializer.is_valid(),它们如何工作?


我需要将用户附加到请求中,这似乎是一件相当普遍的事情,但事实证明这几乎是不可能的。

Django REST框架的文档建议使用序列化程序类的pre_save方法,我做了,但是当调用serializer.is_valid()时它不会被调用,这使得它没有价值,因为没有用户字段串行器验证失败。

我已经看到了一些建议,但它们看起来像疯狂的黑客和/或不起作用。另外,我觉得这是一个太常见的任务,真正需要我看到人们建议的所有东西。我不能成为唯一需要将用户附加到REST请求中创建的对象的人。


11090
2017-11-15 05:08


起源

仅供参考 GitHub上提出了一个问题 关于这一点,但我认为尚未最终确定解决方案。 - David Jones - iPushPull


答案:


假设您正在使用此处描述的身份验证机制之一(或Django Auth):

http://django-rest-framework.org/api-guide/authentication.html, 你有一个

request.user 目的。

创建序列化程序时,在实例化时将其从请求中拉出/传入。

MySerializer(data={"user": request.user, "otherField"=... })

如果你这样做:

MySerializer(data=request.DATA)

你需要复制 request.DATA 目的:

from django.utils.datastructures import MultiValueDict
...
data = MultiValueDict(request.DATA)
data['user'] = request.user
MySerializer(data=data)

5
2017-11-15 07:54





pre_save 被称为 is_valid 但在将实例保存到数据库之前。您需要覆盖验证(使用 def get_validation_exclusions(self): 在该用户序列化程序字段上,因为您将修复验证问题 pre_save。在这里看到我以前的答案:

Django REST Framework序列化器字段required = false

我向DRF的作者提出了这个问题,他们将调查一个更可行的解决方案。


3
2017-11-19 06:08





原来问题是我使用ListAPIView作为我的视图类的基类,并且它没有定义pre_save方法。当我添加一些具有它定义的mixin时,一切都开始工作了。

似乎很奇怪很多基本教程中使用的东西不支持这样的基本功能,但是生活和学习。


2
2018-03-20 19:12



你是如何设法添加呼叫的? pre_save 在序列化器? - Alp
我没有,事实证明pre_save是在视图mixins中定义的,所以我在视图中处理了这个,而不是序列化器。虽然我怀疑ListAPIView使用pre_save,因为它是只读的。 - jmickela
感谢你的回答。您是否可以在视图pre_save方法中访问序列化数据?或者我们应该使用原始REQUEST数据? - Alp
我不知道,我还没有尝试过在pre_save中搞乱序列化数据。 - jmickela


此问题的最佳解决方案是标记填充的必填字段 pre_save 如 read_only_fields 在序列化器中。

为此,请将以下内容添加到序列化程序类:

class MySerializer(serializers.ModelSerializer):
    ...
    class Meta:
        ...
        read_only_fields = ['user', 'my_other_field', ...]

1
2017-09-11 21:50





在新版本的DRF(3.x)中,pre_save被替换为 perform_create 和 perform_update参考


1
2017-07-28 01:18