Django DRF 添加 request.user 到 modelserializer
Django DRF add request.user to modelserializer
我正在使用 django rest 框架,我有一个通过 modelviewset 和 modelserializer 创建的对象。此视图只能由经过身份验证的用户访问,对象应将其 '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" 没有被序列化程序填充。
根据我对文档的理解,这应该将字段添加到序列化程序的验证数据中,作为创建方法的一部分。
显然我误会了什么!
问题在于您的 uploaded_by
字段的 read_only
属性:
Read-only fields are included in the API output, but should not be
included in the input during create or update operations. Any
'read_only' fields that are incorrectly included in the serializer
input will be ignored.
Set this to True to ensure that the field is used when serializing a
representation, but is not used when creating or updating an instance
during deserialization.
基本上它用于显示对象的表示,但不包括在任何更新和创建过程中。
相反,您可以覆盖 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
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)
更清洁的方式:
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")
我正在使用 django rest 框架,我有一个通过 modelviewset 和 modelserializer 创建的对象。此视图只能由经过身份验证的用户访问,对象应将其 '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" 没有被序列化程序填充。
根据我对文档的理解,这应该将字段添加到序列化程序的验证数据中,作为创建方法的一部分。
显然我误会了什么!
问题在于您的 uploaded_by
字段的 read_only
属性:
Read-only fields are included in the API output, but should not be included in the input during create or update operations. Any 'read_only' fields that are incorrectly included in the serializer input will be ignored.
Set this to True to ensure that the field is used when serializing a representation, but is not used when creating or updating an instance during deserialization.
基本上它用于显示对象的表示,但不包括在任何更新和创建过程中。
相反,您可以覆盖 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
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)
更清洁的方式:
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")