Получить текущего пользователя в сериализаторе модели
Можно ли получить текущего пользователя в сериализаторе модели? Я бы хотел сделать это, не отрываясь от дженериков, так как это простая задача, которая должна быть выполнена.
Моя модель:
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
}
Ответы
Ответ 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