Django-rest-framework: ¿Cómo establecer un tipo de campo en SerializerMethodField para la generación de esquemas OpenAPI?

Creado en 13 ene. 2020  ·  3Comentarios  ·  Fuente: encode/django-rest-framework

Considere este serializador inútil:

class MySerializer(serializers.Serializer):

    random_number = serializers.SerializerMethodField()

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

Suponiendo que agregó este serializador en un punto final y generó el esquema de OpenAPI, el serializador se vería así:

properties:
  random_number:
    type: string
  required:
  - random_number

El problema aquí es que no hay forma de decirle a DRF que use type: number aquí. Pensé en algunas posibilidades:

  • Un atributo output_field , como serializers.SerializerMethodField(output_field=serializers.IntegerField()) , similar a las expresiones de consulta de Django
  • Un decorador, como openapi_type(serializers.SerializerMethodField(), serializers.IntegerField())
  • Un atributo, similar a la configuración de descripciones en acciones de administrador :

    random_number = serializers.SerializerMethodField()
    
    def get_random_number(self):
      return 4
    
    get_random_number.output_field = serializers.IntegerField()
    
  • Simplemente algo que DRF no admite, lo que probablemente debería documentarse en algún lugar como una posible advertencia.
Enhancement Schema Generation

Comentario más útil

Para mí, creo que la API que prefiero es algo que use sugerencias de tipo como:

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

Funciona en todas las versiones de Python admitidas actualmente. Esta idea se usó en https://github.com/encode/django-rest-framework/pull/7089 pero no se separó en otro PR. Mirando esa implementación, parece que no maneja colecciones. En algún momento sería mejor usar un serializador anidado, pero creo que se deben admitir casos simples como List[int] , List[str] , Dict[str, int] etc.

@carlfarrington ¿qué opinas? ¿Vale la pena probar este enfoque o hay problemas con él? Si vale la pena intentarlo, ¿también vale la pena obtener algo básico que pueda manejar tipos básicos e ignorar campos anidados por ahora o querríamos (anidados o no) matrices y objetos desde el principio?

Todos 3 comentarios

Hola @Lucidiot.

Supongo que la forma inmediata de hacer esto sería anular AutoSchema._map_field() .

Puede hacer eso por serializador / vista para esperar el campo en cuestión, o agregar un atributo como usted dice.

Eventualmente llegaremos a algo de esta manera, pero actualmente no estoy seguro de cuál es la mejor opción, en términos de API.

Para mí, creo que la API que prefiero es algo que use sugerencias de tipo como:

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

Funciona en todas las versiones de Python admitidas actualmente. Esta idea se usó en https://github.com/encode/django-rest-framework/pull/7089 pero no se separó en otro PR. Mirando esa implementación, parece que no maneja colecciones. En algún momento sería mejor usar un serializador anidado, pero creo que se deben admitir casos simples como List[int] , List[str] , Dict[str, int] etc.

@carlfarrington ¿qué opinas? ¿Vale la pena probar este enfoque o hay problemas con él? Si vale la pena intentarlo, ¿también vale la pena obtener algo básico que pueda manejar tipos básicos e ignorar campos anidados por ahora o querríamos (anidados o no) matrices y objetos desde el principio?

Promocionaremos y documentaremos map_field() por 3.12. Esa es la forma correcta de hacerlo aquí.

¿Fue útil esta página
0 / 5 - 0 calificaciones