Bagaimana cara mendapatkan Request.User di serializer Django-Rest-Framework?

124

Saya sudah mencoba sesuatu seperti ini, tidak berhasil.

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

Saya membutuhkan cara untuk dapat mengakses request.user dari kelas Serializer saya.

PythonIsGreat
sumber
DRF CurrentUserDefaultbenar-benar ❤️ django-rest-framework.org/api-guide/validators/…
andilabs

Jawaban:

231

Anda tidak dapat mengakses request.usersecara langsung. Anda perlu mengakses objek permintaan, lalu mengambil atribut pengguna.

Seperti ini:

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

Atau agar lebih aman,

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

Lebih lanjut tentang konteks tambahan dapat dibaca di sini

karthikr
sumber
1
dikatakanNameError: name 'self' is not defined
Coderaemon
tentu saja, ini dalam konteks kelas. Anda kemungkinan besar tidak berada dalam konteks kelas
karthikr
3
Di serializer saya, dalam validate()metode, self.context adalah dikt kosong. Mengapa?
David D.
14
David - Anda mungkin telah memecahkan masalah ini sejak lama, tetapi jika ada orang lain yang mengalami masalah ini, mungkin karena Anda membuat pembuat serial Anda secara manual. Saya mengalami masalah ini di serializer bersarang yang dipakai untuk hubungan generik. Dokumen mengatakan untuk melakukan serializer = NoteSerializer (nilai) tetapi ini hanya akan meneruskan instance Anda, bukan konteks yang berisi permintaan. Anda dapat meneruskan kwargs ke konstruktor dan mengirimkannya info yang diperlukan (lihat get_serializer atau GenericAPIView untuk mengetahui cara melakukannya)
Jon Vaughan
2
@JonVaughan ada detail bagaimana cara mengirimkan kwargs ke contoh serializer ??
tyan
74

Sebenarnya, Anda tidak perlu repot dengan konteks. Ada cara yang jauh lebih baik untuk melakukannya:

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 Pomaranskiy
sumber
1
Itu tidak berhasil, mengembalikan objek Null. user_edit = serializers.CurrentUserDefault ()
Enderson Menezes
39

Seperti yang disebutkan Igor di jawaban lain, gunakan dapat menggunakan CurrentUserDefault. Jika Anda tidak ingin mengganti metode penyimpanan hanya untuk ini, gunakan doc :

from rest_framework import serializers

class PostSerializer(serializers.ModelSerializer):
    user = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault())
    class Meta:
        model = Post
IJR
sumber
tautan dokumen sekarang salah tautan.
coler-j
Tautan ke dokumentasi resmi DRF dengan contoh yang sama django-rest-framework.org/api-guide/serializers/…
Paolo Melchiorre
2

Anda bisa lewat request.usersaat memanggil ke .save(...)dalam tampilan:

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)

Inilah modelnya:

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)
Max Malysh
sumber
0

Anda perlu sedikit pengeditan di serializer Anda:

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

Berikut adalah contoh, menggunakan Model mixing viewsets. Dalam createmetode, Anda dapat menemukan cara yang tepat untuk memanggil serializer tersebut. Metode get_serializer mengisi kamus konteks dengan benar. Jika Anda perlu menggunakan serializer yang berbeda kemudian ditentukan di viewset, lihat updatemetode tentang cara memulai serializer dengan kamus konteks, yang juga meneruskan objek permintaan ke serializer.

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)
cgl
sumber