Django DRF 将 request.user 添加到模型序列化器

Ale*_*lex 7 django django-serializer django-rest-framework django-rest-viewsets

我正在使用 django rest 框架,并且我有一个通过模型视图集和模型序列化器创建的对象。此视图只能由经过身份验证的用户访问,并且对象应将其“uploaded_by”字段设置为该用户。

我已经阅读了文档,并得出结论,这应该可行

视图集:

class FooViewset(viewsets.ModelViewSet):
    permission_classes = [permissions.IsAdminUser]
    queryset = Foo.objects.all()
    serializer_class = FooSerializer

    def get_serializer_context(self):
        return {"request": self.request}
Run Code Online (Sandbox Code Playgroud)

序列化器:

class FooSerializer(serializers.ModelSerializer):
    uploaded_by = serializers.PrimaryKeyRelatedField(
        read_only=True, default=serializers.CurrentUserDefault()
    )

    class Meta:
        model = Foo
        fields = "__all__"
Run Code Online (Sandbox Code Playgroud)

但是,这会导致以下错误:

django.db.utils.IntegrityError: NOT NULL constraint failed: bar_foo.uploaded_by_id
Run Code Online (Sandbox Code Playgroud)

这表明序列化程序没有填充“uploaded_by”。

根据我对文档的理解,这应该已将该字段添加到来自序列化程序的验证数据中,作为 create 方法的一部分。

显然我误解了一些东西!

Joh*_*han 11

问题在于read_onlyuploaded_by字段上的属性:

只读字段包含在 API 输出中,但不应在创建或更新操作期间包含在输入中。序列化程序输入中错误包含的任何“只读”字段都将被忽略。

将此设置为 True 以确保在序列化表示时使用该字段,但在反序列化期间创建或更新实例时不使用该字段。

来源

基本上它用于显示对象的表示,但不包括在任何更新和创建过程中。

相反,您可以create通过手动分配来覆盖该功能以存储所需的用户。

class FooSerializer(serializers.ModelSerializer):

    uploaded_by = serializers.PrimaryKeyRelatedField(read_only=True)

    def create(self, validated_data):
        foo = Foo.objects.create(uploaded_by=self.context['request'].user,
                                 **validated_data)
        return foo
Run Code Online (Sandbox Code Playgroud)