Django-rest-framework: Como definir um tipo de campo em SerializerMethodField para geração de esquema OpenAPI?

Criado em 13 jan. 2020  ·  3Comentários  ·  Fonte: 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

Supondo que você adicionou este serializador em um endpoint e gerou o esquema OpenAPI, o serializador ficaria assim:

properties:
  random_number:
    type: string
  required:
  - random_number

O problema aqui é que não há como dizer ao DRF para usar type: number aqui. Pensei em algumas possibilidades:

  • Um atributo output_field , como serializers.SerializerMethodField(output_field=serializers.IntegerField()) , semelhante às expressões de consulta do Django
  • Um decorador, como openapi_type(serializers.SerializerMethodField(), serializers.IntegerField())
  • Um atributo, semelhante às descrições de configuração nas ações do administrador :

    random_number = serializers.SerializerMethodField()
    
    def get_random_number(self):
      return 4
    
    get_random_number.output_field = serializers.IntegerField()
    
  • Simplesmente algo que o DRF não suporta, o que provavelmente deve ser documentado em algum lugar como uma possível advertência.
Enhancement Schema Generation

Comentários muito úteis

Para mim, acho que a API que eu prefiro é algo que use dicas de tipo como:

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

Ele funciona em todas as versões do Python atualmente suportadas. Essa ideia foi usada em https://github.com/encode/django-rest-framework/pull/7089, mas não foi separada em outro PR. Olhando para essa implementação, parece que ela não lida com coleções. Em algum ponto, seria melhor usar um serializador aninhado, mas acho que casos simples como List[int] , List[str] , Dict[str, int] etc. devem ser suportados.

@carlfarrington o que você acha? Vale a pena tentar essa abordagem ou há problemas com ela? Se vale a pena tentar, também vale a pena obter algo básico que possa manipular tipos básicos e ignorar campos aninhados por enquanto ou desejaríamos (aninhados ou não) matrizes e objetos desde o início?

Todos 3 comentários

Olá, @Lucidiot.

Acho que a maneira imediata de fazer isso seria sobrescrever AutoSchema._map_field() .

Você pode fazer isso por serializador / visualização para esperar o campo em questão ou adicionar um atributo como você disse.

Nós vamos chegar a algo desta forma eventualmente, mas atualmente não tenho certeza sobre a melhor opção, em termos de API.

Para mim, acho que a API que eu prefiro é algo que use dicas de tipo como:

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

Ele funciona em todas as versões do Python atualmente suportadas. Essa ideia foi usada em https://github.com/encode/django-rest-framework/pull/7089, mas não foi separada em outro PR. Olhando para essa implementação, parece que ela não lida com coleções. Em algum ponto, seria melhor usar um serializador aninhado, mas acho que casos simples como List[int] , List[str] , Dict[str, int] etc. devem ser suportados.

@carlfarrington o que você acha? Vale a pena tentar essa abordagem ou há problemas com ela? Se vale a pena tentar, também vale a pena obter algo básico que possa manipular tipos básicos e ignorar campos aninhados por enquanto ou desejaríamos (aninhados ou não) matrizes e objetos desde o início?

Vamos promover e documentar map_field() por 3.12. Essa é a maneira certa de ir aqui.

Esta página foi útil?
0 / 5 - 0 avaliações