【问题标题】:How to get Request.User in Django-Rest-Framework serializer?如何在 Django-Rest-Framework 序列化程序中获取 Request.User?
【发布时间】:2015-07-24 01:57:13
【问题描述】:

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

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 的方法。

【问题讨论】:

标签: django django-rest-framework


【解决方案1】:

您不能直接访问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

【讨论】:

  • 上面写着NameError: name 'self' is not defined
  • 当然,这是在类的上下文中。你很可能不在一个类的上下文中
  • 在我的序列化程序中,在validate() 方法中,self.context 是一个空字典。为什么?
  • David - 你可能早就解决了这个问题,但如果其他人有这个问题,可能是因为你正在手动构建序列化程序。我在为通用关系实例化的嵌套序列化程序中遇到了这个问题。文档说要执行 serializer = NoteSerializer(value) 但这只会传递您的实例,而不是包含请求的上下文。您可以将 kwargs 传递给构造函数并向其发送所需的信息(请参阅 get_serializer 或 GenericAPIView 了解它是如何做到的)
  • @JonVaughan 任何详细信息如何将 kwargs 传递给序列化程序实例??
【解决方案2】:

实际上,您不必担心上下文。有一个更好的方法来做到这一点:

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

【讨论】:

  • 它不起作用,它返回一个 Null 对象。 user_edit = serializers.CurrentUserDefault()
  • @EndersonMenezes 最好使用IsAuthenticated 权限。
  • 不完全相关,但很有趣:我已经读写 PrimaryKeyRelatedField,我需要过滤当前用户的可能性(即用户地址)。我创建了派生类 MyAddresses(PrimaryKeyRelatedField),并尝试使用 .filter(user=..) 重写 get_queryset()。我在获取 request.user 时遇到问题。此外,我对 user=CurrentUserDefault() 没有成功。但是我已经成功并且可以通过调用它来访问用户: CurrentUserDefault()(self) 成功了。 [self 与 MyAddresses 类/对象有关]
【解决方案3】:

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

from rest_framework import serializers

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

【讨论】:

  • 文档链接现在链接错误。
  • 链接到官方 DRF 文档与此相同的示例 django-rest-framework.org/api-guide/serializers/…
  • 我使用HiddenField 而不是PrimaryKeyRelatedField 没有阅读read_only 属性,它有效。据我了解,没有安全问题。
【解决方案4】:

在视图内调用.save(...) 时可以传递request.user

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)

【讨论】:

  • exclude = ['user'] 为我完成了这项工作。我已将其声明为write_only = True,但不再需要您的解决方案。比将其定义为read_only = True 要清楚得多
【解决方案5】:

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

在views.py中

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

这是传递请求的示例

在 serializers.py 中

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

Source From Rest Framework

【讨论】:

    【解决方案6】:

    在视图中使用此代码:

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

    然后在序列化器中用这个访问它:

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

    【讨论】:

      【解决方案7】:

      您需要在序列化程序中进行小修改:

      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)
      

      【讨论】:

      • 谢谢,对我有帮助。
      【解决方案8】:

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

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

      朝着解决方案前进。

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

      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】:

        对于那些使用 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】:

          您不能直接访问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 
            

          【讨论】:

            【解决方案11】:

            如果您正在使用通用视图并且希望在保存实例时注入当前用户,那么您可以覆盖 perform_createperform_update

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

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

            user = validated_data['user']
            

            【讨论】:

              猜你喜欢
              • 2016-10-03
              • 1970-01-01
              • 2013-11-17
              • 2022-11-22
              • 2021-11-21
              • 1970-01-01
              • 2020-08-02
              • 2014-01-05
              相关资源
              最近更新 更多