简体   繁体   English

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

[英]How to get Request.User in Django-Rest-Framework serializer?

I've tried something like this, it does not work.我试过这样的东西,它不起作用。

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

I need a way of being able to access request.user from my Serializer class.我需要一种能够从我的序列化程序 class 访问 request.user 的方法。

You cannot access the request.user directly.您不能直接访问request.user You need to access the request object, and then fetch the user attribute.您需要访问请求对象,然后获取用户属性。

Like this:像这样:

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

Or to be more safe,或者为了更安全,

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

More on extra context can be read here 可以在此处阅读有关额外上下文的更多信息

Actually, you don't have to bother with context.实际上,您不必理会上下文。 There is a much better way to do it:有一个更好的方法来做到这一点:

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

As Igor mentioned in other answer, you can use CurrentUserDefault.正如 Igor 在其他答案中提到的,您可以使用 CurrentUserDefault。 If you do not want to override save method just for this, then use doc :如果您不想为此覆盖 save 方法,请使用doc

from rest_framework import serializers

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

You can pass request.user when calling .save(...) inside a view:您可以在视图中调用.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)

This is the model:这是模型:

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)

In GET method:在 GET 方法中:

Add context={'user': request.user} in the View class:在View class中添加context={'user': request.user}

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})

Get it in the Serializer class method:在Serializer class方法中获取:

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

    def get_rate(self, instance):
        user = self.context.get("user") 
        ...  
    ...

In POST method:在 POST 方法中:

Follow other answers (eg Max's answer ).按照其他答案(例如Max 的答案)。

CurrentUserDefault A default class that can be used to represent the current user. CurrentUserDefault 可用于表示当前用户的默认类。 In order to use this, the 'request' must have been provided as part of the context dictionary when instantiating the serializer.为了使用它,在实例化序列化程序时,“请求”必须作为上下文字典的一部分提供。

in views.py在views.py中

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

This is example to pass request这是传递请求的示例

in serializers.py在 serializers.py 中

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

Source From Rest Framework 来自 Rest 框架

The solution can be simple for this however I tried accessing using self.contenxt['request'].user but not working in the serializer.解决方案可能很简单,但是我尝试使用self.contenxt['request'].user但没有在序列化程序中工作。

If you're using DRF obviously login via token is the only source or maybe others that's debatable.如果您正在使用 DRF,显然通过令牌登录是唯一的来源,或者其他有争议的来源。

Moving toward a solution.走向解决方案。

Pass the request.user instance while creating serializer.create在创建serializer.create传递request.user实例

views.py视图.py

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

serializer.py序列化程序.py

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

Use this code in view:在视图中使用此代码:

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

then access it with this in serializer:然后在序列化程序中使用它访问它:

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

You can not access self.context.user directly.您不能直接访问self.context.user First you have to pass the context inside you serializer.首先,您必须在序列化程序中传递context For this follow steps bellow:为此,请执行以下步骤:

  1. Some where inside your api view: 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. Then inside your serializer:然后在您的序列化程序中:

     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

You need a small edit in your serializer:您需要在序列化程序中进行小的编辑:

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

Here is an example, using Model mixing viewsets.这是一个使用模型混合视图集的示例。 In create method you can find the proper way of calling the serializer.create方法中,您可以找到调用序列化程序的正确方法。 get_serializer method fills the context dictionary properly. get_serializer方法正确填充上下文字典。 If you need to use a different serializer then defined on the viewset, see the update method on how to initiate the serializer with context dictionary, which also passes the request object to 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)

For those who used Django's ORM and added the user as a foreign key, they will need to include the user's entire object, and I was only able to do this in the create method and removing the mandatory field:对于那些使用 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}}

drf srz pagedrf srz 页面

in my project it worked my user field was read only so i needed to get user id in the create method在我的项目中它工作我的用户字段是只读的所以我需要在创建方法中获取用户 ID

class CommentSerializer(serializers.ModelSerializer):
    comment_replis = RecursiveField(many=True, read_only=True)
    user = UserSerializer(read_only=True)

    class Meta:
        model = PostComment
        fields = ('_all_')

    def create(self, validated_data):
 


        post = PostComment.objects.create(**validated_data)   
        print(self._dict_['_kwargs']['data']["user"]) # geting #request.data["user"] #  <- mian code
        post.user=User.objects.get(id=self._dict_['_kwargs']['data']["user"])
        return post


in my project i tried this way and it work在我的项目中,我尝试过这种方式并且它有效

The best way to get current user inside serializer is like this.让当前用户进入序列化器的最好方法是这样的。

AnySerializer(data={
        'example_id': id
    }, context={'request': request})

This has to be written in views.py And now in Serializer.py part这必须写在 views.py 而现在在 Serializer.py 部分

user = serializers.CharField(default=serializers.CurrentUserDefault())

This "user" must be your field in Model as any relation like foreign key这个“用户”必须是你在 Model 中的字段,因为任何关系都像外键

If you are using generic views and you want to inject current user at the point of saving the instance then you can override perform_create or perform_update :如果您使用的是通用视图并且希望在保存实例时注入当前用户,那么您可以覆盖perform_createperform_update

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

user will be added as an attribute to kwargs and you can access it through validated_data in serializer user将作为属性添加到kwargs ,您可以通过序列化程序中的validated_data访问它

user = validated_data['user']

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Django-Rest-Framework:如何使用request.user为登录用户发布到foreignkey字段 - Django-Rest-Framework: How to post to foreignkey field using request.user for logged in user django-rest-framework中的验证循环,当访问request.user时 - Authentication loop in django-rest-framework when accessing request.user Django(django-rest-framework)寻找最佳实践,以找出进一步的request.user存在于blog.likes中 - Django (django-rest-framework) looking for a best practice to find out wether request.user exists in blog.likes Django REST:序列化程序创建 function request.user not found - Django REST: Serializer create function request.user not found Django Rest Framework - 如何在 views.py 上获取 request.user? - Django Rest Framework - How to get request.user on views.py? 在请求后为序列化器指定django-rest-framework字段? - Specify django-rest-framework field for serializer after request? 根据django-rest-framework序列化器中的请求显示字段 - Display fields based on the request in django-rest-framework serializer Django-Rest-Framework 自定义用户没有散列密码(序列化程序问题) - Django-Rest-Framework Custom User not Hashing Password (Serializer Issue) 如何通过邮递员将发布请求发送到 django-rest-framework 中的嵌套可写序列化程序? - How to send a post request via postman to nested writable serializer in django-rest-framework? 如何访问django-rest-framework的模型序列化器内的用户对象? - How do I access the user object inside the model serializer of django-rest-framework?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM