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

时间:2015-05-13 00:28:25

标签: django django-rest-framework

我尝试过这样的事情,它不起作用。

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']

我需要一种能够从我的Serializer类访问request.user的方法。

11 个答案:

答案 0 :(得分:159)

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

像这样:

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

或者更安全,

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

更多关于extra context can be read here

答案 1 :(得分:63)

实际上,您不必费心上下文。还有一种更好的方法:

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']

答案 2 :(得分:26)

正如Igor在其他答案中提到的,use可以使用CurrentUserDefault。如果您不想仅为此重写保存方法,请使用doc

from rest_framework import serializers

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

答案 3 :(得分:3)

当前用户默认值 可用于表示当前用户的默认类。为了使用它,必须在实例化序列化程序时将“请求”作为上下文字典的一部分提供。

在views.py中

serializer = UploadFilesSerializer(data=request.data, context={'request': request})

这是传递请求的示例

在 serializers.py 中

owner = serializers.HiddenField(
    default=serializers.CurrentUserDefault()
)

Source From Rest Framework

答案 4 :(得分:1)

在视图中使用此代码:

serializer = UploadFilesSerializer(data=request.data, context={'request': request})

然后在序列化程序中使用它访问它:

user = self.context.get("request").user

答案 5 :(得分:1)

您不能直接访问 self.context.user。首先,您必须在序列化程序中传递 context。为此,请执行以下步骤:

  1. api 视图中的某些位置:

     class ApiView(views.APIView):
         def get(self, request):
             items = Item.object.all()
             return Response(
                 ItemSerializer(
                      items, 
                      many=True,
                      context=request  # <- this line (pass the request as context)
                 ).data
             )
    
  2. 然后在你的序列化器中:

     class ItemSerializer(serializers.ModelSerializer):
         current_user = serializers.SerializerMethodField('get_user')
    
         class Meta:
             model = Item
             fields = (
                 'id',
                 'name',
                 'current_user',
             )
    
         def get_user(self, obj):
             request = self.context
             return request.user  # <- here is current your user 
    

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

答案 7 :(得分:0)

在视图内调用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)

答案 8 :(得分:0)

此解决方案可能很简单,但是我尝试使用self.contenxt['request'].user进行访问,但无法在序列化程序中使用。

如果您使用的是DRF,显然通过令牌登录是唯一的来源,或者可能是值得商bat的其他来源。

寻求解决方案。

在创建request.user时传递serializer.create实例

views.py

if serializer.is_valid():
            watch = serializer.create(serializer.data, request.user)

serializer.py

 def create(self, validated_data, usr):
    return Watch.objects.create(user=usr, movie=movie_obj, action=validated_data['action'])

答案 9 :(得分:0)

对于那些使用Django ORM并将用户添加为外键的用户,他们将需要包括用户的整个对象,而我只能在create方法中执行此操作并删除必填字段:

class PostSerializer(serializers.ModelSerializer):

def create(self, validated_data):
    
    request = self.context.get("request")
    
    post = Post()
    post.title = validated_data['title']
    post.article = validated_data['article']
    post.user = request.user

    post.save()

    return post

class Meta:
    model = Post
    fields = '__all__'
    extra_kwargs = {'user': {'required': False}}

答案 10 :(得分:-1)

如果您使用的是通用视图,并且想在保存实例时注入当前用户,则可以覆盖perform_createperform_update

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

user将作为属性添加到kwargs,您可以在序列化程序中通过validated_data进行访问

user = validated_data['user']