Django DRF将request.user添加到Modelerializer

时间:2019-04-06 14:10:37

标签: django django-rest-framework django-serializer django-rest-viewsets

我正在使用django rest框架,并且有一个通过modelviewset和modelerializer创建的对象。该视图只能由经过身份验证的用户访问,并且该对象应将其“ 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方法的一部分。

很明显我误会了一些东西!

3 个答案:

答案 0 :(得分:1)

DRF教程recommend在这种情况下将覆盖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)

答案 1 :(得分:0)

问题出在read_only字段上的uploaded_by属性中:

  

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

     

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

Source

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

相反,您可以通过手动分配功能来覆盖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

答案 2 :(得分: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")