Django-rest-framework: Как установить тип поля в SerializerMethodField для генерации схемы OpenAPI?

Созданный на 13 янв. 2020  ·  3Комментарии  ·  Источник: encode/django-rest-framework

Рассмотрим этот бесполезный сериализатор:

class MySerializer(serializers.Serializer):

    random_number = serializers.SerializerMethodField()

    def get_random_number(self):
        # Chosen by fair dice roll.
        # Guaranteed to be random.
        return 4

Предполагая, что вы добавили этот сериализатор в конечную точку и сгенерировали схему OpenAPI, сериализатор будет выглядеть следующим образом:

properties:
  random_number:
    type: string
  required:
  - random_number

Проблема здесь в том, что нет способа указать DRF использовать здесь type: number . Я подумал о нескольких возможностях:

  • Атрибут output_field , например serializers.SerializerMethodField(output_field=serializers.IntegerField()) , аналогично выражениям запросов Django.
  • Декоратор, например openapi_type(serializers.SerializerMethodField(), serializers.IntegerField())
  • Атрибут, аналогично настройке описаний действий администратора :

    random_number = serializers.SerializerMethodField()
    
    def get_random_number(self):
      return 4
    
    get_random_number.output_field = serializers.IntegerField()
    
  • Просто то, что DRF не поддерживает, что, вероятно, должно быть где-то задокументировано в качестве возможного предостережения.
Enhancement Schema Generation

Самый полезный комментарий

Для меня я думаю, что API, который я бы предпочел, - это что-то, использующее подсказки типа, например:

def get_foo(self, obj) -> int:
    return 1

Он работает во всех поддерживаемых в настоящее время версиях Python. Эта идея использовалась в https://github.com/encode/django-rest-framework/pull/7089, но не была выделена в другой PR. Глядя на эту реализацию, кажется, что она не обрабатывает коллекции. В какой-то момент вам лучше использовать вложенный сериализатор, но я думаю, что должны поддерживаться простые случаи, такие как List[int] , List[str] , Dict[str, int] и т. Д.

@carlfarrington, что ты думаешь? Стоит ли пробовать такой подход или с ним есть проблемы? Если стоит попробовать, стоит ли получить что-то базовое, что может обрабатывать базовые типы и игнорировать вложенные поля на данный момент, или нам нужны (вложенные или нет) массивы и объекты с самого начала?

Все 3 Комментарий

Привет @Lucidiot.

Я предполагаю, что непосредственный способ сделать это - переопределить AutoSchema._map_field() .

Вы можете либо сделать это для каждого сериализатора / представления, чтобы ожидать рассматриваемого поля, либо добавить атрибут, как вы говорите.

В конце концов мы придем к чему-то в этом направлении, но в настоящее время я не уверен в лучшем варианте с точки зрения API.

Для меня я думаю, что API, который я бы предпочел, - это что-то, использующее подсказки типа, например:

def get_foo(self, obj) -> int:
    return 1

Он работает во всех поддерживаемых в настоящее время версиях Python. Эта идея использовалась в https://github.com/encode/django-rest-framework/pull/7089, но не была выделена в другой PR. Глядя на эту реализацию, кажется, что она не обрабатывает коллекции. В какой-то момент вам лучше использовать вложенный сериализатор, но я думаю, что должны поддерживаться простые случаи, такие как List[int] , List[str] , Dict[str, int] и т. Д.

@carlfarrington, что ты думаешь? Стоит ли пробовать такой подход или с ним есть проблемы? Если стоит попробовать, стоит ли получить что-то базовое, что может обрабатывать базовые типы и игнорировать вложенные поля на данный момент, или нам нужны (вложенные или нет) массивы и объекты с самого начала?

Мы продвигаем и документируем map_field() за 3.12. Это правильный путь.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги