Django-Rest-FrameworkシリアライザーでRequest.Userを取得する方法


124

私はこのようなものを試しましたが、うまくいきません。

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クラスからrequest.userにアクセスできる方法が必要です。


DRF CurrentUserDefaultは絶対に❤️django
framework.org

回答:


230

request.user直接アクセスすることはできません。リクエストオブジェクトにアクセスして、ユーザー属性を取得する必要があります。

このような:

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

または、より安全になるために、

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

追加のコンテキストの詳細については、こちらをご覧ください。


1
それは言うNameError: name 'self' is not defined
Coderaemon

もちろん、これはクラスのコンテキストでした。あなたは、クラスのコンテキスト内で最も可能性が高いではありません
karthikr

3
私のシリアライザのvalidate()メソッドでは、self.contextは空のdictです。どうして?
David D.

14
David-あなたはおそらくこれをずっと前に解決したでしょうが、誰かがこの問題を抱えているなら、それはあなたがシリアライザを手動で構築しているためかもしれません。一般的な関係のためにインスタンス化されたネストされたシリアライザーでこの問題が発生しました。ドキュメントはserializer = NoteSerializer(value)を実行するように言っていますが、これはインスタンスのみを渡し、リクエストを含むコンテキストは渡しません。kwargsをコンストラクターに渡し、必要な情報を送信できます(その方法については、get_serializerまたはGenericAPIViewを参照してください)
Jon Vaughan

2
@JonVaughanシリアライザインスタンスにkwargsを渡す方法の詳細
tyan

74

実際、コンテキストに煩わされる必要はありません。それを行うにはもっと良い方法があります:

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

1
動作しませんでした。Nullオブジェクトを返します。user_edit = serializers.CurrentUserDefault()
Enderson Menezes

39

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

ドキュメントリンクが誤ってリンクされるようになりました。
coler-j

この同じ例で公式DRFのドキュメントへのリンクdjango-rest-framework.org/api-guide/serializers/...
パオロMelchiorre

2

ビュー内でrequest.user呼び出すときに渡すことができ.save(...)ます。

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)

0

シリアライザで小さな編集が必要です:

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)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.