Подтвердить что ты не робот

Получить текущего пользователя в сериализаторе модели

Можно ли получить текущего пользователя в сериализаторе модели? Я бы хотел сделать это, не отрываясь от дженериков, так как это простая задача, которая должна быть выполнена.

Моя модель:

class Activity(models.Model):
    number = models.PositiveIntegerField(
        blank=True, null=True, help_text="Activity number. For record keeping only.")
    instructions = models.TextField()
    difficulty = models.ForeignKey(Difficulty)
    categories = models.ManyToManyField(Category)
    boosters = models.ManyToManyField(Booster)

    class Meta():
        verbose_name_plural = "Activities"

Мой сериализатор:

class ActivitySerializer(serializers.ModelSerializer):

    class Meta:
        model = Activity

И мое мнение:

class ActivityDetail(generics.RetrieveUpdateDestroyAPIView):

    queryset = Activity.objects.all()
    serializer_class = ActivityDetailSerializer

Как получить возвращаемую модель с дополнительным полем user, чтобы мой ответ выглядел так:

{
    "id": 1, 
    "difficulty": 1, 
    "categories": [
        1
    ], 
    "boosters": [
        1
    ],
    "current_user": 1 //Current authenticated user here
}
4b9b3361

Ответ 1

Я нашел ответ, просматривая исходный код DRF.

class ActivitySerializer(serializers.ModelSerializer):

    # Create a custom method field
    current_user = serializers.SerializerMethodField('_user')

    # Use this method for the custom field
    def _user(self, obj):
        request = getattr(self.context, 'request', None)
        if request:
            return request.user

    class Meta:
        model = Activity
        # Add our custom method to the fields of the serializer
        fields = ('id','current_user')

Ключевым моментом является тот факт, что методы, определенные внутри ModelSerializer, имеют доступ к своему собственному контексту, который всегда включает в себя запрос (который содержит пользователя при аутентификации). Поскольку мои разрешения предназначены только для аутентифицированных пользователей, здесь всегда должно быть что-то.

Это также может быть сделано в других встроенных сериализаторах djangorestframework.

Как указал Брэден Холт, если ваш user все еще пуст (то есть _user возвращает None), это может быть потому, что сериализатор не был инициализирован с запросом как часть контекста. Чтобы это исправить, просто добавьте контекст запроса при инициализации сериализатора:

serializer = ActivitySerializer(
    data=request.data,
    context={
        'request': request
    }
)

Ответ 2

Контекст передается сериализатору в структуре REST, который содержит запрос по умолчанию. Поэтому вы можете просто использовать self.context['request'].user внутри вашего сериализатора.

Ответ 3

У меня была похожая проблема - я пытался сохранить модель, в которой состоит пользователь, и когда я пытался использовать user = serializers.StringRelatedField(read_only=True, default=serializers.CurrentUserDefault()) как в официальной документации - но выдает ошибку, что пользователь 'null'. Перепишите метод по умолчанию create и получите пользователя из запроса, который мне помог:

class FavoriteApartmentsSerializer(serializers.ModelSerializer):
user = serializers.StringRelatedField(read_only=True, default=serializers.CurrentUserDefault())

class Meta:
    model = FavoriteApartments
    exclude = (
        'date_added',
    )

def create(self, validated_data):
    favoriteApartment = FavoriteApartments(
        apartment=validated_data['apartment'],
        user=self.context['request'].user
    )
    favoriteApartment.save()
    return favoriteApartment

Ответ 4

Я изменил request.data:

serializer = SectionSerializer(data=add_profile_data(request.data, request.user))

def add_profile_data(data, user):
    data['user'] = user.profile.id
    return data