7

我正在使用 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}

序列化器:

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

    class Meta:
        model = Foo
        fields = "__all__"

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

django.db.utils.IntegrityError: NOT NULL constraint failed: bar_foo.uploaded_by_id

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

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

显然我误解了什么!

4

3 回答 3

13

问题在于您字段的read_only属性:uploaded_by

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

将此设置为 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
于 2019-04-06T14:14:12.823 回答
2

DRF 教程建议在这种情况下覆盖perform_create方法,然后进行编辑serializer ,使其反映到新字段

from rest_framework import generics, serializers
from .models import Post


class PostSerializer(serializers.HyperlinkedModelSerializer):
    author = serializers.ReadOnlyField(source='author.username')

    class Meta:
        model = models.Post
        fields = ['title', 'content', 'author']


class ListPost(generics.ListCreateAPIView):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

    def perform_create(self, serializer):
        return serializer.save(author=self.request.user)
于 2020-09-26T15:28:30.173 回答
0

更清洁的方式:

class PostCreateAPIView(CreateAPIView, GenericAPIView):
    queryset = Post.objects.all()
    serializer_class = PostCreationSerializer

    def perform_create(self, serializer):
        return serializer.save(author=self.request.user)

class PostCreationSerializer(serializers.ModelSerializer):
    author = serializers.PrimaryKeyRelatedField(read_only=True)

    class Meta:
        model = Post
        fields = ("content", "author")
于 2021-04-02T10:56:01.770 回答