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

Pyt*_*eat 93 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']
Run Code Online (Sandbox Code Playgroud)

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

kar*_*ikr 182

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

像这样:

user =  self.context['request'].user
Run Code Online (Sandbox Code Playgroud)

或者更安全,

user = None
request = self.context.get("request")
if request and hasattr(request, "user"):
    user = request.user
Run Code Online (Sandbox Code Playgroud)

有关额外背景的更多信息,请参阅此处

  • 大卫 - 你很久以前就解决了这个问题,但是如果其他人有这个问题,可能是因为你正在手动构建你的序列化程序.我在为通用关系实例化的嵌套序列化程序中遇到此问题.文档说要执行serializer = NoteSerializer(value),但这只会传递您的实例,而不是包含请求的上下文.你可以将kwargs传递给构造函数并向它发送它需要的信息(参见get_serializer或GenericAPIView,了解它是如何做到的) (10认同)
  • 在我的序列化器的validate()方法中,self.context是一个空字典。为什么? (3认同)
  • 它说“NameError:名称'self'未定义” (2认同)
  • 当然,这是在课堂上进行的。您很可能不在课堂上 (2认同)
  • @JonVaughan 关于如何将 kwargs 传递给序列化程序实例的任何细节? (2认同)

Igo*_*kiy 68

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

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']
Run Code Online (Sandbox Code Playgroud)

  • 它不起作用,它返回一个 Null 对象。user_edit = 序列化器.CurrentUserDefault() (3认同)
  • @EndersonMenezes 最好使用“IsAuthenticated”权限。 (2认同)

小智 31

正如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
Run Code Online (Sandbox Code Playgroud)

  • 我使用“HiddenField”而不是“PrimaryKeyRelatedField”,没有读取“read_only”属性,它有效。据我了解,不存在安全问题。 (2认同)

小智 18

在视图中使用此代码:

serializer = UploadFilesSerializer(data=request.data, context={'request': request})
Run Code Online (Sandbox Code Playgroud)

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

user = self.context.get("request").user
Run Code Online (Sandbox Code Playgroud)


小智 12

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

在views.py中

serializer = UploadFilesSerializer(data=request.data, context={'request': request})
Run Code Online (Sandbox Code Playgroud)

这是传递请求的示例

在序列化器.py

owner = serializers.HiddenField(
    default=serializers.CurrentUserDefault()
)
Run Code Online (Sandbox Code Playgroud)

来源来自 Rest 框架


Fer*_*oll 10

对于那些使用 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}}
Run Code Online (Sandbox Code Playgroud)


Ben*_*ari 6

在 GET 方法中:

context={'user': request.user}在View类中添加:

class ContentView(generics.ListAPIView):
    def get(self, request, format=None):
        content_list = <Respective-Model>.objects.all()
        serializer = ContentSerializer(content_list, many=True, 
                                       context={'user': request.user})
Run Code Online (Sandbox Code Playgroud)

在Serializer类方法中获取:

class ContentSerializer(serializers.ModelSerializer):
    rate = serializers.SerializerMethodField()

    def get_rate(self, instance):
        user = self.context.get("user") 
        ...  
    ...
Run Code Online (Sandbox Code Playgroud)

在 POST 方法中:

遵循其他答案(例如Max的答案)。


Max*_*ysh 5

您可以在视图内部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)
Run Code Online (Sandbox Code Playgroud)

这是模型:

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)
Run Code Online (Sandbox Code Playgroud)