如何在Django-Rest-Framework序列化程序中获取Request.User?


124

我已经尝试过类似的方法,但是它不起作用。

class PostSerializer(serializers.ModelSerializer):

    class Meta:
        model = Post

    def save(self):
        user = self.context['request.user']
        title = self.validated_data['title']
        article = self.validated_data['article']

我需要一种能够从我的序列化器类访问request.user的方法。


DRF CurrentUserDefault绝对是❤️django- rest
framework.org

Answers:


230

您不能request.user直接访问。您需要访问请求对象,然后获取用户属性。

像这样:

user =  self.context['request'].user

为了更安全,

user = None
request = self.context.get("request")
if request and hasattr(request, "user"):
    user = request.user

可以在这里阅读更多有关额外上下文的信息


1
它说NameError: name 'self' is not defined
Coderaemon

当然,这是在类的上下文中。您很可能不在课堂上
karthikr

3
在我的序列化器的validate()方法中,self.context是一个空字典。为什么?
David D.

14
David-您可能很早就解决了这个问题,但是如果其他任何人都遇到了这个问题,则可能是因为您正在手动构建序列化程序。我在为通用关系实例化的嵌套序列化程序中遇到了这个问题。文档说要做serializer = NoteSerializer(value),但这只会传递您的实例,而不传递包含请求的上下文。您可以将kwargs传递给构造函数,并向其发送所需的信息(有关如何执行的信息,请参见get_serializer或GenericAPIView)
Jon Vaughan

2
@JonVaughan任何详细信息如何将kwargs传递给序列化程序实例?
tyan

74

实际上,您不必理会上下文。有一种更好的方法:

from rest_framework.fields import CurrentUserDefault

class PostSerializer(serializers.ModelSerializer):

    class Meta:
        model = Post

   def save(self):
        user = CurrentUserDefault()  # <= magic!
        title = self.validated_data['title']
        article = self.validated_data['article']

1
它不起作用,它返回一个Null对象。user_edit = serializers.CurrentUserDefault()
Enderson Menezes,

39

正如伊戈尔在其他答案中提到的那样,使用可以使用CurrentUserDefault。如果您不想为此仅覆盖保存方法,请使用doc

from rest_framework import serializers

class PostSerializer(serializers.ModelSerializer):
    user = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault())
    class Meta:
        model = Post

doc链接现在被取消链接。
coler-j

链接到官方DRF文件与此相同的例子django-rest-framework.org/api-guide/serializers/...
保罗Melchiorre旅舍

2

您可以在视图内request.user调用时通过.save(...)

class EventSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.Event
        exclude = ['user']


class EventView(APIView):

    def post(self, request):
        es = EventSerializer(data=request.data)
        if es.is_valid():
            es.save(user=self.request.user)
            return Response(status=status.HTTP_201_CREATED)
        return Response(data=es.errors, status=status.HTTP_400_BAD_REQUEST)

这是模型:

class Event(models.Model):
    user = models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    date = models.DateTimeField(default=timezone.now)
    place = models.CharField(max_length=255)

0

您需要在序列化程序中进行一些小的编辑:

class PostSerializer(serializers.ModelSerializer):

    class Meta:
        model = Post

    def save(self):
        user = self.context['request'].user
        title = self.validated_data['title']
        article = self.validated_data['article']

这是一个使用模型混合视图集的示例。在create方法中,您可以找到调用串行器的正确方法。get_serializer方法正确填充上下文字典。如果需要使用视图集上定义的其他序列化器,请参阅update有关如何使用上下文字典启动序列化器的方法,该方法还将请求对象传递给序列化器。

class SignupViewSet(mixins.UpdateModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet):

    http_method_names = ["put", "post"]
    serializer_class = PostSerializer

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=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, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        kwargs['context'] = self.get_serializer_context()
        serializer = PostSerializer(instance, data=request.data, partial=partial, **kwargs)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)    
        return Response(serializer.data)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.