Come ottenere Request.User nel serializzatore Django-Rest-Framework?


124

Ho provato qualcosa di simile, non funziona.

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

Ho bisogno di un modo per poter accedere a request.user dalla mia classe Serializer.


DRF CurrentUserDefaultè assolutamente ❤️ django-rest-framework.org/api-guide/validators/…
andilabs

Risposte:


231

Non è possibile accedere request.userdirettamente al file. È necessario accedere all'oggetto richiesta e quindi recuperare l'attributo utente.

Come questo:

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

O per essere più sicuro,

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

Maggiori informazioni sul contesto extra possono essere lette qui


1
diceNameError: name 'self' is not defined
Coderaemon

ovviamente, questo era nel contesto di una classe.
Molto

3
Nel mio serializzatore, in validate()method, self.context è un dict vuoto. Perché?
David D.

14
David: probabilmente l'hai risolto molto tempo fa, ma se qualcun altro ha questo problema, potrebbe essere perché stai costruendo il serializzatore manualmente. Ho riscontrato questo problema in un serializzatore annidato istanziato per una relazione generica. I documenti dicono di fare serializer = NoteSerializer (value) ma questo passerà solo la tua istanza, non il contesto contenente la richiesta. Puoi passare kwarg al costruttore e inviargli le informazioni di cui ha bisogno (vedi get_serializer o GenericAPIView per come lo fa)
Jon Vaughan

2
@JonVaughan qualche dettaglio su come passare kwargs all'istanza del serializzatore ??
tyan

74

In realtà, non devi preoccuparti del contesto. C'è un modo molto migliore per farlo:

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
Non ha funzionato, restituisce un oggetto Null. user_edit = serializers.CurrentUserDefault ()
Enderson Menezes

39

Come accennato da Igor in un'altra risposta, use può utilizzare CurrentUserDefault. Se non vuoi sovrascrivere il metodo di salvataggio solo per questo, usa doc :

from rest_framework import serializers

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

il link al documento è ora errato.
coler-j

Link alla documentazione ufficiale DRF con questo stesso esempio django-rest-framework.org/api-guide/serializers/…
Paolo Melchiorre

2

Puoi passare request.userquando chiami .save(...)all'interno di una vista:

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)

Questo è il modello:

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

Hai bisogno di una piccola modifica nel tuo serializzatore:

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

Di seguito è riportato un esempio, utilizzando le visualizzazioni di mixaggio di modelli. In createmethod puoi trovare il modo corretto di chiamare il serializzatore. Il metodo get_serializer riempie correttamente il dizionario di contesto. Se è necessario utilizzare un serializzatore diverso da quello definito nel viewet, vedere il updatemetodo su come avviare il serializzatore con il dizionario di contesto, che passa anche l'oggetto della richiesta al serializzatore.

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.