Decorators
The primary mechanism for adding content to your schema is by decorating your endpoints. If you have
used sanic-openapi
in the past, this should be familiar to you. The decorators and their arguments match closely
the OAS v3.0 specification.
All of the examples show will wrap around a route definition. When you are creating these, you should make sure that
your Sanic route decorator (@app.route
, @app.get
, etc) is the outermost decorator. That is to say that you should
put that first and then one or more of the below decorators after.
from sanic_ext import openapi
@app.get("/path/to/<something>")
@openapi.summary("This is a summary")
@openapi.description("This is a description")
async def handler(request, something: str):
...
You will also see a lot of the below examples reference a model object. For the sake of simplicity, the examples will
use UserProfile
that will look like this. The point is that it can be any well-typed class. You could easily imagine
this being a dataclass
or some other kind of model object.
class UserProfile:
name: str
age: int
email: str
Definition decorator#
@openapi.definition
#
The @openapi.definition
decorator allows you to define all parts of an operations on a path at once. It is an omnibums
decorator in that it has the same capabilities to create operation definitions as the rest of the decorators. Using
multiple field-specific decorators or a single decorator is a style choice for you the developer.
The fields are purposely permissive in accepting multiple types to make it easiest for you to define your operation.
Arguments
Field | Type |
---|---|
body |
**dict, RequestBody, *YourModel*** |
deprecated |
bool |
description |
str |
document |
str, ExternalDocumentation |
exclude |
bool |
operation |
str |
parameter |
str, dict, Parameter, [str], [dict], [Parameter] |
response |
dict, Response, YourModel, [dict], [Response] |
summary |
str |
tag |
str, Tag, [str], [Tag] |
secured |
Dict[str, Any] |
Examples
@openapi.definition(
body=RequestBody(UserProfile, required=True),
summary="User profile update",
tag="one",
response=[Success, Response(Failure, status=400)],
)
See below examples for more examples. Any of the values for the below decorators can be used in the corresponding keyword argument.
Field-specific decorators#
All the following decorators are based on @openapi
body#
Arguments
Field | Type |
---|---|
content | ***YourModel*, dict, RequestBody** |
Examples
@openapi.body(UserProfile)
@openapi.body({"application/json": UserProfile})
@openapi.body(RequestBody({"application/json": UserProfile}))
@openapi.body({"content": UserProfile})
@openapi.body(RequestBody(UserProfile))
@openapi.body({"application/json": {"description": ...}})
deprecated#
Arguments
None
Examples
@openapi.deprecated()
@openapi.deprecated
description#
Arguments
Field | Type |
---|---|
text |
str |
Examples
@openapi.description(
"""This is a **description**.
## You can use `markdown`
- And
- make
- lists.
"""
)
document#
Arguments
Field | Type |
---|---|
url |
str |
description |
str |
Examples
@openapi.document("http://example.com/docs")
@openapi.document(ExternalDocumentation("http://example.com/more"))
exclude#
Can be used on route definitions like all of the other decorators, or can be called on a Blueprint
Arguments
Field | Type | Default |
---|---|---|
flag |
bool | True |
bp |
Blueprint |
Examples
@openapi.exclude()
openapi.exclude(bp=some_blueprint)
operation#
Sets the operation ID.
Arguments
Field | Type |
---|---|
name |
str |
Examples
@openapi.operation("doNothing")
Arguments
Field | Type | Default |
---|---|---|
name |
str | |
schema |
type | str |
location |
"query", "header", "path" or "cookie" | "query" |
Examples
@openapi.parameter("thing")
@openapi.parameter(parameter=Parameter("foobar", deprecated=True))
@openapi.parameter("Authorization", str, "header")
@openapi.parameter("thing", required=True, allowEmptyValue=False)
response#
Arguments
If using a Response
object, you should not pass any other arguments.
Field | Type |
---|---|
status |
int |
content |
***type, *YourModel, dict** |
description |
str |
response |
Response |
Examples
@openapi.response(200, str, "This is endpoint returns a string")
@openapi.response(200, {"text/plain": str}, "...")
@openapi.response(response=Response(UserProfile, description="..."))
@openapi.response(
response=Response(
{
"application/json": UserProfile,
},
description="...",
status=201,
)
)
@openapi.response(200, UserProfile, "...")
@openapi.response(
200,
{
"application/json": UserProfile,
},
"Description...",
)
summary#
Arguments
Field | Type |
---|---|
text |
str |
Examples
@openapi.summary("This is an endpoint")
tag#
Arguments
Field | Type |
---|---|
*args |
str, Tag |
Examples
@openapi.tag("foo")
@openapi.tag("foo", Tag("bar"))
secured#
Arguments
Field | Type |
---|---|
*args, **kwargs |
str, Dict[str, Any] |
Examples
@openapi.secured()
@openapi.secured("foo")
@openapi.secured("token1", "token2")
@openapi.secured({"my_api_key": []})
@openapi.secured(my_api_key=[])
Do not forget to use add_security_scheme
. See security for more details.
``
Integration with Pydantic#
Pydantic models have the ability to generate OpenAPI schema.
To take advantage of Pydantic model schema generation, pass the output in place of the schema.
from sanic import Sanic, json
from sanic_ext import validate, openapi
from pydantic import BaseModel, Field
@openapi.component
class Item(BaseModel):
name: str
description: str = None
price: float
tax: float = None
class ItemList(BaseModel):
items: List[Item]
app = Sanic("test")
@app.get("/")
@openapi.definition(
body={
"application/json": ItemList.schema(
ref_template="#/components/schemas/{model}"
)
},
)
async def get(request):
return json({})
Note
It is important to set that ref_template
. By default Pydantic will select a template that is not standard OAS. This will cause the schema to not be found when generating the final document.
Added in v22.9