Есть ли простой способ сериализовать только непустые поля с помощью 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 вызывается как для одиночного, так и для списочного сериализатора, он работает в обоих случаях.

Вернуться на верх