[英]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)
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")
...
...
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})
in serializers.py在 serializers.py 中
owner = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
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:为此,请执行以下步骤:
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 )
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}}
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_create
或perform_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.