如何获取请求。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']

我需要一种能够访问请求的方法。用户从我的Serializer类。

129452 次浏览

你不能直接访问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。如果你不想为此重写save方法,那么使用医生:

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

下面是一个使用Model混合视图集的示例。在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显然登录通过令牌是唯一的来源或其他可能是有争议的。

朝着解决方案前进。

在创建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'])

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

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

user将作为属性添加到kwargs中,你可以在序列化器中通过validated_data访问它

user = validated_data['user']

对于那些使用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}}
< p > CurrentUserDefault 可用于表示当前用户的默认类。为了使用这个,'request'必须在实例化序列化器时作为上下文字典的一部分提供

在views.py

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

这是传递请求的示例

在serializers.py

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

Rest Framework来源

在视图中使用以下代码:

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

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

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

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

drf SRZ page

在我的项目中,它工作了我的用户字段是只读的,所以我需要得到 create方法中的用户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方法中:

在View类中添加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})

在Serializer类方法中获取:

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


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

POST方法:

遵循其他答案(例如马克斯的回答)。