Fastapi: [FEATURE] Way to tie OpenAPI Examples to a pydantic model

Created on 30 May 2019  路  13Comments  路  Source: tiangolo/fastapi

The problem
I would like to tie a schema example to my pydantic model, but currently the only way to do it is to declare the example when you're using the model, as far as I can understand. It's document here: https://fastapi.tiangolo.com/tutorial/body-schema/#schema-extras.

The solution I would like
It would be nice if possible to have something like an __example__ attribute on the model that could be tied directly to the the OpenAPI schema itself. Like the first example under Request and Response Body Examples at https://swagger.io/docs/specification/adding-examples/.

Example
Something along the lines of this:

class Item(BaseModel):
    name: str
    description: str = None
    price: float
    tax: float = None

    __example__ = {
        "name": "Foo",
        "description": "A very nice Item",
        "price": 35.4,
        "tax": 3.2,
    }

I don't know if that specific method makes sense or is possible or right, but the general idea of tying examples to the schema itself would be nice.

enhancement

Most helpful comment

For completeness, there are new docs about adding examples that show up in Swagger UI: https://fastapi.tiangolo.com/tutorial/schema-extra-example/

All 13 comments

I was thinking the same thing, but then I ran across a situation where I wanted to use the same model with different example data in different endpoints. I think it makes more sense to set the example data at the endpoint as it's currently done.

Could there not be the option to do either? The option is there in OpenAPI. You can do it either response specific, request specific, or schema specific.

+1 for this feature. I'd definitely prefer to be able to set a "default" example regardless of how exactly it was translated into the OpenAPI schema.

This would actually be a feature request for Pydantic.

I've had something like this in mind, but haven't been able to implement/propose it there.

I wondered if that would be the case. I'll open up an issue over there. Love the work you're doing @tiangolo ! Absolutely love FastAPI.

For reference, here's the other issue if you want to follow that one: https://github.com/samuelcolvin/pydantic/issues/627#issue-462217004

You should now be able to use Pydantic models with schema_extra in FastAPI 0.38.0 :rocket: :tada:

E.g.

class Person(BaseModel):
    name: str
    age: int

    class Config:
        schema_extra = {
            'examples': [
                {
                    'name': 'John Doe',
                    'age': 25,
                }
            ]
        }

@tiangolo seems not working in responses args of router.METHOD

from fastapi.applications import FastAPI
from pydantic import BaseModel


class Person(BaseModel):
    name: str
    age: int

    class Config:
        schema_extra = {
            'examples': [{
                'name': 'John Doe',
                'age': 25,
            }]
        }


app = FastAPI()


@app.get('/router', responses={200: {'model': Person}})
async def handler():
    return "hello world"


if __name__ == '__main__':
    import sys
    import fastapi
    print('python version', sys.version)
    print('fastapi version', fastapi.__version__)
    import json
    print(json.dumps(app.openapi(), indent=2, ensure_ascii=False))

python version 3.7.4 (tags/v3.7.4:e09359112e, Jul 8 2019, 20:34:20) [MSC v.1916 64 bit (AMD64)]
fastapi version 0.38.1

{
  "openapi": "3.0.2",
  "info": {
    "title": "Fast API",
    "version": "0.1.0"
  },
  "paths": {
    "/router": {
      "get": {
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "summary": "Handler",
        "operationId": "handler_router_get"
      }
    }
  },
  "components": {
    "schemas": {
      "Person": {
        "title": "Person",
        "required": [
          "name",
          "age"
        ],
        "type": "object",
        "properties": {
          "name": {
            "title": "Name",
            "type": "string"
          },
          "age": {
            "title": "Age",
            "type": "integer"
          }
        }
      }
    }
  }
}

Typo: "examples" should be "example"

from fastapi.applications import FastAPI
from pydantic import BaseModel


class Person(BaseModel):
    name: str
    age: int

    class Config:
        schema_extra = {
             'example': [{
                'name': 'John Doe',
                'age': 25,
            }]
        }


app = FastAPI()


@app.get('/router', responses={200: {'model': Person}})
async def handler():
    return "hello world"


if __name__ == '__main__':
    import sys
    import fastapi
    print('python version', sys.version)
    print('fastapi version', fastapi.__version__)
    import json
    print(json.dumps(app.openapi(), indent=2, ensure_ascii=False))

python version 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 16:52:21)
[Clang 6.0 (clang-600.0.57)]
fastapi version 0.38.1

{
  "openapi": "3.0.2",
  "info": {
    "title": "Fast API",
    "version": "0.1.0"
  },
  "paths": {
    "/router": {
      "get": {
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "summary": "Handler",
        "operationId": "handler_router_get"
      }
    }
  },
  "components": {
    "schemas": {
      "Person": {
        "title": "Person",
        "required": [
          "name",
          "age"
        ],
        "type": "object",
        "properties": {
          "name": {
            "title": "Name",
            "type": "string"
          },
          "age": {
            "title": "Age",
            "type": "integer"
          }
        },
        "example": [
          {
            "name": "John Doe",
            "age": 25
          }
        ]
      }
    }
  }
}

@zamiramir thank you

@Trim21 were you able to find a way to make this work with responses?

I've tried and it isn't working for me.

This is my schemas.py

from pydantic import BaseModel

class Gene(BaseModel):
    id: str
    name: str
    species: str

    class Config:
        orm_mode = True
        schema_extra = {
            'example': [
                {
                    'id': 'val',
                    'name': 'val1',
                    'species': 'val2'
                }
            ]
        }

and this is my function where I'm trying to use this model so that there's an example in the response schema, in the docs

from . import schemas

@app.get("/gene_search/", responses={200: {'model': schemas.Gene}})
def gene_search(name: str = Query(..., min_length = 3), species: str = None, limit: int = 10):
    filters = [Gene.name.like("{}%".format(name))]
    if species:
        filters.append(Gene.species == species)
    filters = tuple(filters)
    genes = session.query(Gene.id, Gene.name, Gene.species).filter(*filters).limit(limit)
    return [gene._asdict() for gene in genes]

But this doesn't get reflected on the docs. Any idea what I'm doing wrong here?

Also, is using a pydantic model / schema the only way to show a response example?

For completeness, there are new docs about adding examples that show up in Swagger UI: https://fastapi.tiangolo.com/tutorial/schema-extra-example/

Hey folks, is it possible to specify examples for objects and properties (would be in the components.schemas section of OpenAPI)?

e: Nevermind, I found how to do this in the docs. Thank you for the fantastic documentation, maintainers!

Hmmm, it seems that the "examples" key word is also supported now, see: https://swagger.io/docs/specification/adding-examples/
In this case, it's a list. I saw #822 and PR #1267 but there is no feedback on this.

Was this page helpful?
0 / 5 - 0 ratings