Як отримати Request.User у серіалізаторі Django-Rest-Framework?


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

Мені потрібен спосіб отримати доступ до request.user з мого класу Serializer.


DRF CurrentUserDefaultабсолютно ❤️ django-rest-framework.org/api-guide/validators/…
andilabs

Відповіді:


231

Ви не можете отримати доступ 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 - це порожній вислів. Чому?
Девід Д.

14
Девід - ви, мабуть, вирішили це давно, але якщо хтось ще має це питання, це може бути тому, що ви конструюєте свій серіалізатор вручну. У мене була ця проблема у вкладеному серіалізаторі, створеному для загальних відносин. Документи кажуть робити serializer = NoteSerializer (значення), але це передасть лише ваш примірник, а не контекст, що містить запит. Ви можете передати конструктору 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

Як згадував Ігор в іншій відповіді, використання може використовувати CurrentUserDefault. Якщо ви не хочете замінити метод збереження саме для цього, використовуйте doc :

from rest_framework import serializers

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

doc-посилання тепер посилається неправильно.
coler-j

Посилання на офіційну документацію DRF з цим самим прикладом django-rest-framework.org/api-guide/serializers/…
Paolo 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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.