Como obter Request.User no serializador Django-Rest-Framework?


124

Já tentei algo assim, não funciona.

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

Preciso de uma maneira de acessar request.user da minha classe Serializer.


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

Respostas:


230

Você não pode acessar o request.userdiretamente. Você precisa acessar o objeto de solicitação e, em seguida, buscar o atributo do usuário.

Como isso:

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

Ou para ser mais seguro,

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

Mais sobre contexto extra pode ser lido aqui


1
dizNameError: name 'self' is not defined
Coderaemon

é claro, isso foi no contexto de uma aula. Você provavelmente não está no contexto de uma classe
karthikr

3
Em meu serializador, em validate()método, self.context é um dict vazio. Por quê?
David D.

14
David - você provavelmente já resolveu isso há muito tempo, mas se alguém mais tiver esse problema, pode ser porque você está construindo seu serializador manualmente. Eu tive esse problema em um serializador aninhado instanciado para um relacionamento genérico. Os documentos dizem para fazer serializer = NoteSerializer (value), mas isso só vai passar sua instância, não o contexto que contém a solicitação. Você pode passar kwargs para o construtor e enviar a ele as informações de que precisa (consulte get_serializer ou GenericAPIView para saber como ele faz isso)
Jon Vaughan

2
@JonVaughan algum detalhe de como passar kwargs para a instância do serializador ??
tyan

74

Na verdade, você não precisa se preocupar com o contexto. Existe uma maneira muito melhor de fazer isso:

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
Não funcionou, está retornando um objeto Nulo. user_edit = serializers.CurrentUserDefault ()
Enderson Menezes

39

Como Igor mencionou em outra resposta, use pode usar CurrentUserDefault. Se você não deseja substituir o método de salvamento apenas por isso, use doc :

from rest_framework import serializers

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

o link doc agora está com link incorreto.
coler-j

Link para a documentação oficial do DRF com este mesmo exemplo django-rest-framework.org/api-guide/serializers/…
Paolo Melchiorre

2

Você pode passar request.userao chamar .save(...)dentro de uma visualização:

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)

Este é o modelo:

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

Você precisa de uma pequena edição em seu serializador:

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

Aqui está um exemplo, usando conjuntos de visualizações de combinação de modelo. No createmétodo, você pode encontrar a maneira adequada de chamar o serializador. O método get_serializer preenche o dicionário de contexto corretamente. Se você precisar usar um serializador diferente do definido no conjunto de visualizações, consulte o updatemétodo sobre como iniciar o serializador com dicionário de contexto, que também passa o objeto de solicitação para o serializador.

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)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.