Передать контекст запроса в сериализатор из режима просмотра в Django Rest Framework
У меня есть случай, когда значения для поля сериализатора зависят от идентификатора текущего пользователя. Я видел, как добавить пользователя в контекст при инициализации сериализатора, но я не уверен, как это сделать при использовании ViewSet, поскольку вы поставляете только класс serializer, а не фактический экземпляр serializer.
В основном я хотел бы знать, как перейти от:
class myModelViewSet(ModelViewSet):
queryset = myModel.objects.all()
permission_classes = [DjangoModelPermissions]
serializer_class = myModelSerializer
в
class myModelSerializer(serializers.ModelSerializer):
uploaded_by = serializers.SerializerMethodField()
special_field = serializers.SerializerMethodField()
class Meta:
model = myModel
def get_special_field(self, obj):
if self.context['request'].user.has_perm('something.add_something'):
return something
Извините, если это было неясно, из DOC:
Добавление дополнительного контекста
Который говорит, чтобы сделать
serializer = AccountSerializer(account, context={'request': request})
serializer.data
Но я не уверен, как сделать это автоматически из viewet, так как я могу изменить только класс serializer, а не сам экземпляр serializer.
Ответы
Ответ 1
GenericViewSet
имеет метод get_serializer_context
, который вы можете переопределить:
class myModelViewSet(ModelViewSet):
queryset = myModel.objects.all()
permission_classes = [DjangoModelPermissions]
serializer_class = myModelSerializer
def get_serializer_context(self):
return {'request': self.request}
Ответ 2
Возврат родительского контекста в переопределенной функции get_serializer_context
облегчит доступ к запросу и его данным.
class myModelViewSet(ModelViewSet):
queryset = myModel.objects.all()
permission_classes = [DjangoModelPermissions]
serializer_class = myModelSerializer
def get_serializer_context(self):
"""
pass request attribute to serializer
"""
context = super(myModelViewSet, self).get_serializer_context()
return context
Это очень стабильно, поскольку каждый раз, когда мы запрашиваем viewet, он также возвращает контекст.
Ответ 3
значения для поля сериализатора зависят от идентификатора текущего пользователя
Вот как я обрабатываю такие случаи в моем ModelViewSet:
def perform_create(self, serializer):
user = self.request.user
if user.username == 'myuser':
serializer.data['myfield'] = 'something'
serializer.save()
Ответ 4
просто используйте get_serializer() в ваших представлениях
def get_serializer(self, *args, **kwargs):
"""
Return the serializer instance that should be used for validating and
deserializing input, and for serializing output.
"""
serializer_class = self.get_serializer_class()
kwargs['context'] = self.get_serializer_context()
return serializer_class(*args, **kwargs)