Ответ
В Django Rest Framework (DRF) существует несколько способов кастомизировать сериализацию данных в ModelViewSet, что позволяет гибко управлять выводом API.
1. Использование разных сериализаторов для разных действий
Это самый чистый и рекомендуемый способ, когда для разных действий (например, list и retrieve) требуются разные наборы полей. Для этого переопределяется метод get_serializer_class.
Пример: Показать краткую информацию в списке и полную в детальном представлении.
class UserListSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'username', 'email')
class UserDetailSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'username', 'email', 'first_name', 'last_name', 'is_staff')
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
def get_serializer_class(self):
if self.action == 'list':
return UserListSerializer
# Для 'retrieve', 'create', 'update' и др. будет использован UserDetailSerializer
return UserDetailSerializer
2. Переопределение метода to_representation в сериализаторе
Этот метод подходит для небольших, условных изменений в представлении данных. Он позволяет модифицировать словарь с данными непосредственно перед его отправкой в ответе.
Пример: Добавить вычисляемое поле или изменить формат существующего.
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'first_name', 'last_name')
def to_representation(self, instance):
# Получаем стандартное представление
representation = super().to_representation(instance)
# Добавляем новое поле 'full_name'
representation['full_name'] = f"{instance.first_name} {instance.last_name}"
return representation
3. Переопределение методов действий (list, retrieve)
Этот способ даёт полный контроль над ответом. Он полезен, когда нужно не только изменить данные, но и добавить в ответ метаинформацию или выполнить сложную логику.
Пример: Добавить в ответ на list общее количество объектов.
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserListSerializer
def list(self, request, *args, **kwargs):
queryset = self.get_queryset()
serializer = self.get_serializer(queryset, many=True)
# Формируем кастомный ответ
custom_data = {
'count': queryset.count(),
'results': serializer.data
}
return Response(custom_data)