Добавить поле в сериализатор drf динамически

У меня есть конечная точка API, которая возвращает список объектов одной из моих моделей. У меня есть очень простой сериализатор, который в настоящее время возвращает все поля модели.

Теперь мне нужно добавить в этот сериализатор еще одно поле, которое вычисляется путем применения логики к одному из полей модели, и другую структуру данных, которая также вычисляется динамически, но должна вычисляться только один раз для каждого вызова API.

Как передать эту структуру сериализатору для каждого вызова API, но не для каждого объекта, который возвращает сериализатор?

Мой ModelViewSet (без дополнительного поля) довольно тривиален:

class MyModelViewset(ModelViewSet):
    queryset = SomeModel.objects.all()
    serializer_class = SomeModelSerializer

person Andy Thomas    schedule 17.10.2018    source источник


Ответы (1)


Несколько советов о том, как этого добиться:

  • Чтобы вычислить что-то только один раз и использовать это в сериализаторе, вы должны добавить это в сериализатор контекст.
  • Вы можете создать @property в своем классе SomeModel, и его можно будет открыть через поля сериализатора только для чтения. В Django также есть @cached_property, так что значение вычисляется только один раз и сохраняется до тех пор, пока работает экземпляр
  • Вы можете использовать поле SerializerMethodField, если хотите что-то вычислить (у вас есть доступ к контексту сериализатора).

Просто быстрый пример того, как это использовать.

class MyModelViewset(ModelViewSet):
    queryset = SomeModel.objects.all()
    serializer_class = SomeModelSerializer

    def get_serializer_context(self):
        context = super().get_serializer_context()
        context['my_value'] =  [] # calculate something here, you have access to self.request
        return context

class SomeModelSerializer(serializers.ModelSerializer):
    my_data = serializers.SerializerMethodField()

    class Meta:
        model = SomeModel

    def get_my_data(self, obj):
        # you have access to self.context['my_value']
        # you have access to obj.some_property
        return my_data
person Gabriel Muj    schedule 17.10.2018