Давайте возьмем базовую комбинацию ModelViewset
и ModelSerializer
здесь :) Это будет похоже на
# serializers.py
class SampleSerializer(serializers.ModelSerializer):
class Meta:
model = SampleModel
fields = '__all__'
# views.py
class SampleViewset(viewsets.ModelViewSet):
queryset = SampleModel.objects.all()
serializer_class = SampleSerializer
Почему DRF возвращает все данные обратно клиенту?
Здесь SampleViewset
использует SampleSerializer
каждый раз, и он будет сериализован все поля , определенные в классе сериализатора.Согласно текущей конфигурации
Какое возможное решение?
Возможное решение для этого - остановить процесс сериализации некоторых полей некоторыми способами :)
Как это сделать?
Насколько я знал, это можно сделать двумя способами.
1. Использовать минимальный класс SampleSerializer
для метода POST
2. переопределить to_representation()
метод SampleSerializer
для POST
запросов
Метод-1: использовать другой сериализатор
Определитьновый класс сериализатора с полями, которые вы хотите отправлять и получать, в то время как POST
запрос
class SampleSerializerMinimal(serializers.ModelSerializer):
class Meta:
model = SampleModel
fields = ('id', 'name', 'age')
Теперь мы должны указать наборам просмотра использовать этоСериализатор для методов POST, это можно сделать в get_serializer_class()
набора
class SampleViewset(viewsets.ModelViewSet):
queryset = SampleModel.objects.all()
serializer_class = SampleSerializer
<b>def get_serializer_class(self):
if self.request.method == 'POST':
return SampleSerializerMinimal
return SampleSerializer</b>
Метод 2: Переопределить метод to_representation()
class SampleSerializer(serializers.ModelSerializer):
class Meta:
model = SampleModel
fields = '__all__'
<b>def to_representation(self, instance):
try:
if self.context['view'].request.method == 'POST':
return {
"id": instance.id,
"name": instance.name,
"age": instance.age
}
except KeyError:
return super(SampleSerializer, self).to_representation(instance)
return super(SampleSerializer, self).to_representation(instance)</b>
Как лучше?
Я чувствовал Метод-1 - это более подходящий способ работы, но вы можетеНе добавляйте id
только к fields
, потому что для запроса POST может потребоваться больше полей.
Method-2
тоже хорошо, но не так многоочистить, если вы хотите вернуть n
поля и записать его в своем to_representation()
методе
UPDATE-1
Метод 3: комбинация method-1
и method-2
# serializer.py
class <b>SampleSerializerMinimal</b>(serializers.ModelSerializer):
class Meta:
model = SampleModel
fields = ('id', 'name', 'age')
<b>def to_representation(self, instance):
"""
we don't have to check the request method, because DRF routing only POSt requests to this serializer
"""
return {"id": instance.id}</b>
# views.py
class SampleViewset(viewsets.ModelViewSet):
queryset = SampleModel.objects.all()
serializer_class = SampleSerializer
<b>def get_serializer_class(self):
if self.action.method == 'POST':
return SampleSerializerMinimal
return SampleSerializer</b>
ОБНОВЛЕНИЕ-2
Имеет ли смысл такая практика предотвращения полной сериализации объектов, созданных с помощью POST, в отношении шаблонов проектирования RESTful, подхода, идеологии и т. Д.?
.data
вызывает to_representation()
метод, который вызывает связанные объекты и все другие поля в сериализаторе .( Исходный код свойства data
сериализатора ) Так что, если вы можете избежать этого вызова .data
, было бы неплохо!.
Поскольку я видел много ответов API с единственной детализацией, такой как {"status":true}
после запроса POST, я не думаю, что ваш подход излишне убивает шаблоны DRF и другие вещи
Действительно ли это позволит избежать выбора всех связанных данных (а также выполнения каких-либо SerializerMethodFields и т. Д.?
Да. Как я уже говорил выше, этоне будет вызывать процесс сериализации, пока не будет вызван .data