如何在 Django-Rest-Framework 序列化程序中获取 Request.User?
How to get Request.User in Django-Rest-Framework 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']
我需要一种能够从我的序列化程序 class 访问 request.user 的方法。
您无法直接访问 request.user
。您需要访问请求对象,然后获取用户属性。
像这样:
user = self.context['request'].user
或者为了更安全,
user = None
request = self.context.get("request")
if request and hasattr(request, "user"):
user = request.user
实际上,您不必为上下文烦恼。有更好的方法:
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']
正如 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
您需要在您的序列化程序中进行小的修改:
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)
在视图中调用 .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)
这个解决方案很简单,但是我尝试使用 self.contenxt['request'].user
进行访问,但没有在序列化程序中工作。
如果您正在使用 DRF,显然通过令牌登录是唯一的来源,或者其他可能值得商榷的来源。
正在寻求解决方案。
创建时传递 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'])
如果您使用的是通用视图,并且想在保存实例时注入当前用户,那么您可以覆盖 perform_create
或 perform_update
:
def perform_create(self, serializer):
serializer.save(user=self.request.user)
user
将作为属性添加到 kwargs
中,您可以通过序列化器
中的 validated_data
访问它
user = validated_data['user']
对于那些使用 Django 的 ORM 并将用户添加为外键的人,他们将需要包括用户的整个对象,而我只能在创建方法中做到这一点并删除必填字段:
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}}
当前用户默认
可用于表示当前用户的默认 class。为了使用它,'request' 必须在实例化序列化程序时作为上下文字典的一部分提供。
在views.py
serializer = UploadFilesSerializer(data=request.data, context={'request': request})
这是传递请求的示例
在serializers.py
owner = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
在视图中使用此代码:
serializer = UploadFilesSerializer(data=request.data, context={'request': request})
然后在序列化器中用这个访问它:
user = self.context.get("request").user
您无法直接访问 self.context.user
。首先,您必须在序列化程序中传递 context
。为此,请执行以下步骤:
您 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
)
然后在你的序列化器中:
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
在我的项目中它起作用了我的用户字段是只读的所以我需要得到
创建方法中的用户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
在我的项目中,我尝试过这种方式并且有效
在 GET 方法中:
在视图中添加 context={'user': request.user}
class:
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})
在Serializerclass方法中获取:
class ContentSerializer(serializers.ModelSerializer):
rate = serializers.SerializerMethodField()
def get_rate(self, instance):
user = self.context.get("user")
...
...
在POST方法中:
关注其他答案(例如 )。
我试过类似的方法,但没有用。
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']
我需要一种能够从我的序列化程序 class 访问 request.user 的方法。
您无法直接访问 request.user
。您需要访问请求对象,然后获取用户属性。
像这样:
user = self.context['request'].user
或者为了更安全,
user = None
request = self.context.get("request")
if request and hasattr(request, "user"):
user = request.user
实际上,您不必为上下文烦恼。有更好的方法:
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']
正如 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
您需要在您的序列化程序中进行小的修改:
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)
在视图中调用 .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)
这个解决方案很简单,但是我尝试使用 self.contenxt['request'].user
进行访问,但没有在序列化程序中工作。
如果您正在使用 DRF,显然通过令牌登录是唯一的来源,或者其他可能值得商榷的来源。
正在寻求解决方案。
创建时传递 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'])
如果您使用的是通用视图,并且想在保存实例时注入当前用户,那么您可以覆盖 perform_create
或 perform_update
:
def perform_create(self, serializer):
serializer.save(user=self.request.user)
user
将作为属性添加到 kwargs
中,您可以通过序列化器
validated_data
访问它
user = validated_data['user']
对于那些使用 Django 的 ORM 并将用户添加为外键的人,他们将需要包括用户的整个对象,而我只能在创建方法中做到这一点并删除必填字段:
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}}
当前用户默认 可用于表示当前用户的默认 class。为了使用它,'request' 必须在实例化序列化程序时作为上下文字典的一部分提供。
在views.py
serializer = UploadFilesSerializer(data=request.data, context={'request': request})
这是传递请求的示例
在serializers.py
owner = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
在视图中使用此代码:
serializer = UploadFilesSerializer(data=request.data, context={'request': request})
然后在序列化器中用这个访问它:
user = self.context.get("request").user
您无法直接访问 self.context.user
。首先,您必须在序列化程序中传递 context
。为此,请执行以下步骤:
您 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 )
然后在你的序列化器中:
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
在我的项目中它起作用了我的用户字段是只读的所以我需要得到 创建方法中的用户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
在我的项目中,我尝试过这种方式并且有效
在 GET 方法中:
在视图中添加 context={'user': request.user}
class:
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})
在Serializerclass方法中获取:
class ContentSerializer(serializers.ModelSerializer):
rate = serializers.SerializerMethodField()
def get_rate(self, instance):
user = self.context.get("user")
...
...
在POST方法中:
关注其他答案(例如