Django Rest Framework:从序列化器中的视图访问传递的参数

Django Rest Framework: Access to passed arguments from views in serializers

在问这个问题之前,我看到了以下链接,但它们对我没有任何帮助:

我有一个作者模型,它有默认 Django 用户模型的外键:

apps/author/models.py

class Author(models.Model):
    user = models.OneToOneField(
        User,
        related_name='author',
        on_delete=models.CASCADE,
        default="",
    )

    is_author = models.BooleanField(
        default=True,
    )

    full_name = models.CharField(
        max_length=100,
        default="",
    )

    def __str__(self):
        return self.user.username

Post 模型有指向 Author 的外键。

apps/posts/models.py

class Post(models.Model):
    author = models.ForeignKey(
        Author,
        related_name="posts",
        on_delete=models.CASCADE,
    )

    title = models.TextField(
        null=True,
        blank=True,
    )

    content = models.TextField(
        null=True,
        blank=True,
    )

    is_draft = models.BooleanField(
        default=True
    )

    created_at = models.DateTimeField(
        auto_now_add=True,
        null=True,
    )

    published_at = models.DateField(
        null=True,
        blank=True,
        default=None,
    )

    def __str__(self):
        return str(self.id) + ", " + self.title

问题定义: 为了创建一个新的 post,我在视图中从 self.request.user 获取当前用户,并将其传递给Post序列化器。但是每当我想使用以下对 localhost:8000/posts/ 的请求创建一个新的 post 时,我都会遇到错误:

# I also added JWT authorization header to the postman! and it doesn't have any problem at this level
{
    "title": "",
    "content": ""
}

错误

这是我在 apps/posts/views.py 中所做的:

def get_serializer_context(self):
    context = super().get_serializer_context()
    context["user"] = self.request.user
    context["author"] = Author.objects.get(user=context["user"])
    print(context["author"])
    return context

print(context["author"]) 运行良好并打印出当前作者。问题是我无法在序列化程序中获取它。

class PostSerializer(serializers.ModelSerializer):
    # author = serializers.SerializerMethodField('get_author')
    #
    # def get_author(self, obj):
    #     print('current author', self.context["author"])
    #     return self.context["author"]

    class Meta:
        model = Post
        fields = '__all__'
        extra_fields = ['author']

    #def create(self, validated_data):
        #print(self.context["author"])
        #print(self.context)

PS: 评论是我试过的方法,还是报错。我该如何解决这个问题?

也许你应该在 PostSerializer 的作者字段中添加“required=False”,这将避免“此字段是必需的”错误。

class PostSerializer(serializers.ModelSerializer):
    author = serializers.PrimaryKeyRelatedField(required=False)

您使用什么视图?如果你使用 GenericAPIView 及其子类,上下文将传递给序列化器,默认 get_serializer_context 将默认传递请求。如果不是,您应该手动传递上下文。

class PostSerializer(serializers.ModelSerializer):
    author = serializers.PrimaryKeyRelatedField(required=False)

    def create(self, validated_data):
        request = self.context.get('request')
        author = Author.objects.get(user=request.user)
        # ....


class PostView(mixins.CreateModelMixin, viewsets.GenericViewSet):
    serializer_class = PostSerializer

    def create(self, request, *args, **kwargs):
        super().create(request, *args, **kwargs)

更新:

我错了,有更简单的解决方法:


这应该是最简单的方法。

class PostViewSet(viewsets.ModelViewSet):
    # ... other implementations

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data={"author": request.user.author.id, **request.data})
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def update(self, request, pk, *args, **kwargs):
        try:
            post = Post.objects.get(pk=pk)
        except Post.DoesNotExist:
            raise NotFound("Post doesn't exist.")

        if post.author != request.user.author:
            raise PermissionDenied('Permission Denied!')

        serializer = PostSerializer(post, data={"author": request.user.author.id, **request.data})
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)
        return Response(serializer.data)
    

这是默认方法,除了传递 author 数据。

您可能需要检查用户是否有 author 关系。