Есть ли простой способ сериализовать только непустые поля с помощью ModelSerializer'а Django Rest Framework?
Я работаю над проектом Django с рядом довольно больших моделей (около 80 полей). Я использую ModelSerializer из Django Rest Framework для сериализации моделей, а ViewSets для обеспечения API для моего фронтенда.
Это работает очень хорошо, но я хотел бы уменьшить количество данных, передаваемых сервером. Большинство полей моей модели являются необязательными, и многие экземпляры имеют значения только для нескольких из них. В этих случаях я хотел бы сериализовать только те поля, которые имеют значения (т.е. которые являются истинными).
Я представляю, что могу сделать это либо на стороне сериализатора, либо на стороне модели, но я не совсем понимаю, как эти двое разговаривают друг с другом, так сказать.
Мой текущий сериализатор очень прост:
class OutfitSerializer(serializers.ModelSerializer):
class Meta:
model = Outfit
fields = '__all__'
Мнение столь же простое:
# Outfit views
class OutfitViewSet(viewsets.ViewSet):
def list(self, request):
queryset = Outfit.objects.all()
serializer = OutfitSerializer(queryset, many=True)
return Response(serializer.data)
Я возился с подклассификацией сериализатора и модификацией функции __init__ (вдохновленный этой частью документации DRF):
class NonEmptyFieldsModelSerializer(serializers.ModelSerializer):
"""
ModelSerializer that allows fields to be set at runtime via the
optional 'fields' argument
Copied from https://www.django-rest-framework.org/api-guide/serializers/#dynamically-modifying-fields
"""
def __init__(self, *args, **kwargs):
super(NonEmptyFieldsModelSerializer, self).__init__(*args, **kwargs)
all_fields = set(self.fields)
for field_name in all_fields:
# IF THIS FIELD IS EMPTY IN THE OBJECT CURRENTLY BEING SERIALIZED:
self.fields.pop(field_name)
но я не уверен, как и есть ли у меня доступ к текущему объекту в __init__. Я также не совсем понимаю, как это будет работать для сериализации целого набора запросов: Будет ли инициализироваться новый экземпляр сериализатора для каждого экземпляра модели?
Я мог бы просто написать функцию сериализатора для самой модели, но это в некотором роде разрушило бы цель использования Django Rest Framework, поскольку мне пришлось бы настраивать каждое поле отдельно.
Итак, как я могу сериализовать только непустые поля экземпляра модели?
Вы можете переопределить to_representation
метод ModelSerializer:
class NonEmptySerializer(ModelSerializer):
def to_representation(self, instance):
ret = super().to_representation(instance)
non_null_ret = copy.deepcopy(ret)
for key in ret.keys():
if not ret[key]:
non_null_ret.pop(key)
return non_null_ret
Затем наследовать от этого сериализатора, когда это необходимо:
class OutfitSerializer(NonEmptySerializer):
class Meta:
model = Outfit
fields = '__all__'
Поскольку to_representation
вызывается как для одиночного, так и для списочного сериализатора, он работает в обоих случаях.