Wie bekomme ich Request.User in Django-Rest-Framework Serializer?

123

Ich habe so etwas versucht, es funktioniert nicht.

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

Ich benötige eine Möglichkeit, über meine Serializer-Klasse auf request.user zugreifen zu können.

PythonIsGreat
quelle
DRF CurrentUserDefaultist absolut j django-rest-framework.org/api-guide/validators/…
andilabs

Antworten:

229

Sie können nicht request.userdirekt auf die zugreifen . Sie müssen auf das Anforderungsobjekt zugreifen und dann das Benutzerattribut abrufen.

So was:

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

Oder um sicherer zu sein,

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

Weitere Informationen zum zusätzlichen Kontext finden Sie hier

karthikr
quelle
1
es heißtNameError: name 'self' is not defined
Coderaemon
Dies geschah natürlich im Rahmen einer Klasse. Sie sind höchstwahrscheinlich nicht im Kontext einer Klasse
karthikr
3
In meinem Serializer ist in der validate()Methode self.context ein leeres Diktat. Warum?
David D.
14
David - Sie haben das wahrscheinlich schon vor langer Zeit gelöst, aber wenn jemand anderes dieses Problem hat, könnte dies daran liegen, dass Sie Ihren Serializer manuell erstellen. Ich hatte dieses Problem in einem verschachtelten Serializer, der für eine generische Beziehung instanziiert wurde. Die Dokumente sagen, dass serializer = NoteSerializer (Wert) ausgeführt werden soll, dies übergibt jedoch nur Ihre Instanz, nicht den Kontext, der die Anforderung enthält. Sie können kwargs an den Konstruktor übergeben und ihm die benötigten Informationen senden (siehe get_serializer oder GenericAPIView, wie es funktioniert)
Jon Vaughan
2
@ JonVaughan irgendwelche Details, wie kwargs an die Serializer-Instanz übergeben werden?
Tyan
74

Eigentlich muss man sich nicht mit dem Kontext beschäftigen. Es gibt einen viel besseren Weg, dies zu tun:

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
quelle
1
Es hat nicht funktioniert, es hat ein Null-Objekt zurückgegeben. user_edit = serializers.CurrentUserDefault ()
Enderson Menezes
39

Wie Igor in einer anderen Antwort erwähnt hat, kann use CurrentUserDefault verwenden. Wenn Sie die Speichermethode nicht nur dafür überschreiben möchten, verwenden Sie doc :

from rest_framework import serializers

class PostSerializer(serializers.ModelSerializer):
    user = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault())
    class Meta:
        model = Post
IJR
quelle
doc link ist jetzt falsch verlinkt.
Coler-J
Link zur offiziellen DRF-Dokumentation mit demselben Beispiel django-rest-framework.org/api-guide/serializers/…
Paolo Melchiorre
2

Sie können übergeben, request.userwenn Sie in .save(...)einer Ansicht aufrufen :

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)

Dies ist das Modell:

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
quelle
0

Sie benötigen eine kleine Bearbeitung in Ihrem 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']

Hier ist ein Beispiel für die Verwendung von Modell-Mischansichten. In der createMethode finden Sie die richtige Methode zum Aufrufen des Serializers. Die Methode get_serializer füllt das Kontextwörterbuch ordnungsgemäß aus. Wenn Sie einen anderen Serializer als den im Viewset definierten verwenden müssen, lesen Sie die updateMethode zum Initiieren des Serializers mit dem Kontextwörterbuch, das auch das Anforderungsobjekt an den Serializer übergibt.

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
quelle