簡體   English   中英

如何在 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。 如果您不想為此覆蓋 save 方法,請使用doc

from rest_framework import serializers

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

您可以在視圖中調用.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)

在 GET 方法中:

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

在Serializer class方法中獲取:

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

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

在 POST 方法中:

按照其他答案(例如Max 的答案)。

CurrentUserDefault 可用於表示當前用戶的默認類。 為了使用它,在實例化序列化程序時,“請求”必須作為上下文字典的一部分提供。

在views.py中

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

這是傳遞請求的示例

在 serializers.py 中

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

來自 Rest 框架

解決方案可能很簡單,但是我嘗試使用self.contenxt['request'].user但沒有在序列化程序中工作。

如果您正在使用 DRF,顯然通過令牌登錄是唯一的來源,或者其他有爭議的來源。

走向解決方案。

在創建serializer.create傳遞request.user實例

視圖.py

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

序列化程序.py

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

在視圖中使用此代碼:

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

您需要在序列化程序中進行小的編輯:

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)

對於那些使用 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 頁面

在我的項目中它工作我的用戶字段是只讀的所以我需要在創建方法中獲取用戶 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


在我的項目中,我嘗試過這種方式並且它有效

讓當前用戶進入序列化器的最好方法是這樣的。

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

這必須寫在 views.py 而現在在 Serializer.py 部分

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

這個“用戶”必須是你在 Model 中的字段,因為任何關系都像外鍵

如果您使用的是通用視圖並且希望在保存實例時注入當前用戶,那么您可以覆蓋perform_createperform_update

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

user將作為屬性添加到kwargs ,您可以通過序列化程序中的validated_data訪問它

user = validated_data['user']

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM