Introduction
Hello everyone, today I would like to introduce to you a framework API that I just scratched a few weeks ago. Why do I recommend this framework, this is because the slogan of this team is so eye-catching.
FastAPI framework, high performance, easy to learn, fast to code, ready for production
So what is fastAPI, please read the next section.
Concept
FastApi is a web framework used to build a high performance API, easy to code, simple but also good support for making products.
Characteristics:
- Fast : Performance is as high as NodeJS and Go.
- Fast to code : Faster code, speed of code features increase about 200 to 300%.
- Fewer bugs : By simplicity, reduce the number of developper bugs by 40%.
- Intuitive : easier code support with auto-suggestion, and debugging took less time than before.
- Easy : designed to be easy to use and easy to learn.
- Short : Minimal code iteration. The passed parameters have many features. Little bugs.
- Robust : powerful performance, interoperable API via docs.
Setting
Requirements: Python 3.6+.
FastAPI is based on OpenAPI (formerly called Swagger), the web part is supported by Starlette, while the data is supported by Pydantic.
FastAPI CLI
To install this framework on Ubuntu, you need a python version ≥ geq ≥ 3.6.
1 2 | pip install fastapi |
You also need an ASGI server when deploying a product like Uvicorn or Hypercorn.
1 2 | pip install uvicorn |
A little bit about ASGI, ASGI inherits from WSGI. WSGI is a communication standard between web server and Python application server. Previously, there was mod_python of Apache, but because it was not developed and not safe, WSGI was born. WSGI has the following effects:
- WSGI is flexible: developers can convert web components like Gunicorn to uWSGI.
- WSGI processes many requests at the same time replacing the webserver and decides which request is passed to the web application. The illustration of stealing at the page ( fullstackpython.com ):
If WSGI is the standard for synchronous Python apps
then ASGI is the standard for synchronous
and asynchronous
Python apps
. ASGI is suitable for all applications using WSGI due to its backward compatibility mechanism.
Okay enough, we continue to find out what utilities FastAPI also provides.
FastAPI Docs
Due to being based on OpenAI, which was formerly known as Swagger, FastAPI provides doc with easy-to-see and easy-to-use interface. Illustration:
When enabling the doc with the local url http://0.0.0.0:8000/docs
.
1 other FastAPI interface docs http://0.0.0.0:8000/redoc
.
Performance
You can test the performance of web frameworks on this page ( https://www.techempower.com/benchmarks/ )
Optional Depencies
Since FastAPI is based on Pydantic and Starlette, it’s okay to have additional support for some additional libraries:
Pydantic:
ujson
: JSON “parsing” is faster.email_validator
: validate email.
Starlette:
requests
: when you want to make a request, useTestClient
.aiofiles
: when you want to useFileResponse
orStaticFile
.jinja2
: if you want to use the default config templates.python-multipart
: supports “parsing” with request.form ().itsdangerous
:SessionMiddleware
support.graphene
:GraphQL
support.
FastAPI:
uvicorn
: ASGI server caters to your application.orjson
: if you want to useORJSONResponse
.
If you want to use all of the above libraries, you just need to use one simple command.
1 2 | pip install fastapi[all] |
Basic instructions
Create a simple API
Basically, the code is as easy as eating candy, you create a main.py
file.
1 2 3 4 5 6 7 8 9 | <span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI <span class="token comment">#import class FastAPI() từ thư viện fastapi</span> app <span class="token operator">=</span> FastAPI <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment"># gọi constructor và gán vào biến app</span> <span class="token decorator annotation punctuation">@app <span class="token punctuation">.</span> get</span> <span class="token punctuation">(</span> <span class="token string">"/"</span> <span class="token punctuation">)</span> <span class="token comment"># giống flask, khai báo phương thức get và url</span> <span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">root</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token comment"># do dùng ASGI nên ở đây thêm async, nếu bên thứ 3 không hỗ trợ thì bỏ async đi</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token string">"message"</span> <span class="token punctuation">:</span> <span class="token string">"Hello World"</span> <span class="token punctuation">}</span> |
Then run this line of code to run the app
1 2 | uvicorn main:app --host 0.0.0.0 --port 8000 |
P / S: If you do it in development environment can add --reload
to automatically restart after code change.
Then go to check the results of the broadcast http://127.0.0.1:8000/docs
.
Click Try it out
-> Execute
-> API returns the response.
This API interface is based on OpenAPI. On that side there is a concept to define API called “Schema”. If you are curious, please visit this link http://127.0.0.1:8000/openapi.json
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <span class="token punctuation">{</span> <span class="token property">"openapi"</span> <span class="token operator">:</span> <span class="token string">"3.0.2"</span> <span class="token punctuation">,</span> <span class="token property">"info"</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"title"</span> <span class="token operator">:</span> <span class="token string">"FastAPI"</span> <span class="token punctuation">,</span> <span class="token property">"version"</span> <span class="token operator">:</span> <span class="token string">"0.1.0"</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token property">"paths"</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"/"</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"get"</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"summary"</span> <span class="token operator">:</span> <span class="token string">"Root"</span> <span class="token punctuation">,</span> <span class="token property">"operationId"</span> <span class="token operator">:</span> <span class="token string">"root__get"</span> <span class="token punctuation">,</span> <span class="token property">"responses"</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"200"</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"description"</span> <span class="token operator">:</span> <span class="token string">"Successful Response"</span> <span class="token punctuation">,</span> <span class="token property">"content"</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"application/json"</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"schema"</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Generally speaking, you only need 6 steps to create an API
- Step 1: import fastapi
- Step 2: Create an instance of class FastAPI
- Step 3: create path, starting from
/
- Step 4: declare HTTP method: post, get, put, delete or options, head, patch, trace
- Step 5: function declaration
- Step 6: Return content with format dict, list, str, int, …
Path Parameters
You can pass the param over the path.
1 2 3 4 5 6 7 8 9 | <span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI app <span class="token operator">=</span> FastAPI <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token decorator annotation punctuation">@app <span class="token punctuation">.</span> get</span> <span class="token punctuation">(</span> <span class="token string">"/items/{item_id}"</span> <span class="token punctuation">)</span> <span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">read_item</span> <span class="token punctuation">(</span> item_id <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token string">"item_id"</span> <span class="token punctuation">:</span> item_id <span class="token punctuation">}</span> |
The variable item_id
on the path will pass to the read_item function with the same param named item_id
. Test http://127.0.0.1:8000/items/foo
.
Path parameters with types
You can also declare the format of the param to return when passing a well-formatted variable that will return a value.
1 2 3 4 5 6 7 8 9 | <span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI app <span class="token operator">=</span> FastAPI <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token decorator annotation punctuation">@app <span class="token punctuation">.</span> get</span> <span class="token punctuation">(</span> <span class="token string">"/items/{item_id}"</span> <span class="token punctuation">)</span> <span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">read_item</span> <span class="token punctuation">(</span> item_id <span class="token punctuation">:</span> <span class="token builtin">int</span> <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token string">"item_id"</span> <span class="token punctuation">:</span> item_id <span class="token punctuation">}</span> |
Data validation
If the format is not correct, a message is returned. All validated data is based on Pydantic.
Order
If you have declared duplicate paths like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI app <span class="token operator">=</span> FastAPI <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token decorator annotation punctuation">@app <span class="token punctuation">.</span> get</span> <span class="token punctuation">(</span> <span class="token string">"/users/me"</span> <span class="token punctuation">)</span> <span class="token comment"># <- here</span> <span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">read_user_me</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token string">"user_id"</span> <span class="token punctuation">:</span> <span class="token string">"the current user"</span> <span class="token punctuation">}</span> <span class="token decorator annotation punctuation">@app <span class="token punctuation">.</span> get</span> <span class="token punctuation">(</span> <span class="token string">"/users/{user_id}"</span> <span class="token punctuation">)</span> <span class="token comment"># <- and here</span> <span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">read_user</span> <span class="token punctuation">(</span> user_id <span class="token punctuation">:</span> <span class="token builtin">str</span> <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token string">"user_id"</span> <span class="token punctuation">:</span> user_id <span class="token punctuation">}</span> |
Remember to order /users/me
first and then /users/{user_id}
later, otherwise if /users/{user_id}
first, you will think that “user_id” gets the value me
.
Path in path
FastAPI supports declaring the path in the API path thanks to based Starlette.
1 2 3 4 | /files/{file_path} file_path = /home/johndoe/myfile.txt => /files/home/johndoe/myfile.txt |
1 2 3 4 5 6 7 8 9 | <span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI app <span class="token operator">=</span> FastAPI <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token decorator annotation punctuation">@app <span class="token punctuation">.</span> get</span> <span class="token punctuation">(</span> <span class="token string">"/files/{file_path:path}"</span> <span class="token punctuation">)</span> <span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">read_file</span> <span class="token punctuation">(</span> file_path <span class="token punctuation">:</span> <span class="token builtin">str</span> <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token string">"file_path"</span> <span class="token punctuation">:</span> file_path <span class="token punctuation">}</span> |
Query Parameters
If you pass the param as key-value, then in FastAPI there is support called “query” parameters.
1 2 3 4 5 6 7 8 9 10 11 | <span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI app <span class="token operator">=</span> FastAPI <span class="token punctuation">(</span> <span class="token punctuation">)</span> fake_items_db <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> <span class="token string">"item_name"</span> <span class="token punctuation">:</span> <span class="token string">"Foo"</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token string">"item_name"</span> <span class="token punctuation">:</span> <span class="token string">"Bar"</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token string">"item_name"</span> <span class="token punctuation">:</span> <span class="token string">"Baz"</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span> <span class="token comment"># pair format: key-value</span> <span class="token decorator annotation punctuation">@app <span class="token punctuation">.</span> get</span> <span class="token punctuation">(</span> <span class="token string">"/items/"</span> <span class="token punctuation">)</span> <span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">read_item</span> <span class="token punctuation">(</span> skip <span class="token punctuation">:</span> <span class="token builtin">int</span> <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">,</span> limit <span class="token punctuation">:</span> <span class="token builtin">int</span> <span class="token operator">=</span> <span class="token number">10</span> <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token keyword">return</span> fake_items_db <span class="token punctuation">[</span> skip <span class="token punctuation">:</span> skip <span class="token operator">+</span> limit <span class="token punctuation">]</span> <span class="token comment"># trả về dữ liệu từ skip đến skip + limit</span> |
Check it at the link http://127.0.0.1:8000/items/?skip=0&limit=10
:
If you notice that the skip and limit are formatted string as a path, but once passed to the function, they will be converted from string to int.
Optional parameters
In addition, FastAPI provides a way to declare optional
query parameters, the default is None.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token keyword">from</span> typing <span class="token keyword">import</span> Optional <span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI app <span class="token operator">=</span> FastAPI <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token decorator annotation punctuation">@app <span class="token punctuation">.</span> get</span> <span class="token punctuation">(</span> <span class="token string">"/items/{item_id}"</span> <span class="token punctuation">)</span> <span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">read_item</span> <span class="token punctuation">(</span> item_id <span class="token punctuation">:</span> <span class="token builtin">str</span> <span class="token punctuation">,</span> q <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">str</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token triple-quoted-string string">''' param item_id: format string param q: format string, default value: None, Optional: help you find error that happen '''</span> <span class="token keyword">if</span> q <span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token string">"item_id"</span> <span class="token punctuation">:</span> item_id <span class="token punctuation">,</span> <span class="token string">"q"</span> <span class="token punctuation">:</span> q <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token string">"item_id"</span> <span class="token punctuation">:</span> item_id <span class="token punctuation">}</span> |
As you can see above, param passed in the path is item_id
, but in the function, param is also q
. FastAPI only uses str
to determine the param format, and Optional
is not used FastAPI, only checks the error if it occurs.
You can test with the following link.
1 2 | http://127.0.0.1:8000/items/1?q=1 # 1 là item_id và ?q=1 là giá trị của q |
Query parameter type conversion
Change the default value by passing the value on the path.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI app <span class="token operator">=</span> FastAPI <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token decorator annotation punctuation">@app <span class="token punctuation">.</span> get</span> <span class="token punctuation">(</span> <span class="token string">"/items/{item_id}"</span> <span class="token punctuation">)</span> <span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">read_item</span> <span class="token punctuation">(</span> item_id <span class="token punctuation">:</span> <span class="token builtin">str</span> <span class="token punctuation">,</span> short <span class="token punctuation">:</span> <span class="token builtin">bool</span> <span class="token operator">=</span> <span class="token boolean">False</span> <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token comment"># param short với định dạng boolean có giá trị mặc định là False</span> item <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token string">"item_id"</span> <span class="token punctuation">:</span> item_id <span class="token punctuation">}</span> <span class="token keyword">if</span> <span class="token keyword">not</span> short <span class="token punctuation">:</span> item <span class="token punctuation">.</span> update <span class="token punctuation">(</span> <span class="token punctuation">{</span> <span class="token string">"description"</span> <span class="token punctuation">:</span> <span class="token string">"This is an amazing item that has a long description"</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> item |
In this case
1 2 3 4 | http://127.0.0.1:8000/items/foo?short=1 or http://127.0.0.1:8000/items/foo?short=True |
Multiple path and query parameters
With nested paths, FastAPI knows which param with which param based on param name.
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI app <span class="token operator">=</span> FastAPI <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token decorator annotation punctuation">@app <span class="token punctuation">.</span> get</span> <span class="token punctuation">(</span> <span class="token string">"/users/{user_id}/items/{item_id}"</span> <span class="token punctuation">)</span> <span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">read_user_item</span> <span class="token punctuation">(</span> user_id <span class="token punctuation">:</span> <span class="token builtin">int</span> <span class="token punctuation">,</span> item_id <span class="token punctuation">:</span> <span class="token builtin">str</span> <span class="token punctuation">)</span> <span class="token punctuation">:</span> item <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token string">"item_id"</span> <span class="token punctuation">:</span> item_id <span class="token punctuation">,</span> <span class="token string">"owner_id"</span> <span class="token punctuation">:</span> user_id <span class="token punctuation">}</span> <span class="token keyword">return</span> item |
Required query parameters
Simply fill in the missing param on the path will error
1 2 3 4 5 6 7 8 9 10 | from fastapi import FastAPI app = FastAPI() @app.get("/items/{item_id}") async def read_user_item(item_id: str, needy: str): item = {"item_id": item_id, "needy": needy} return item |
As shown below, I just pass the value of item_id
and the value of needy
should not generate an error.
Request Body
- Request body: the user sends the request from the browser to the API.
- Response body: Based on the request, APi returns a response to the user.
To declare the format of the request body, you need to use Pydantic
models. P / S: prompted when sending a request to use the POST method, if you use the GET method, you will be exposed information on the URL => not high security.
Pydantic Models
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <span class="token keyword">from</span> typing <span class="token keyword">import</span> Optional <span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI <span class="token keyword">from</span> pydantic <span class="token keyword">import</span> BaseModel <span class="token comment"># import class BaseModel của thư viện pydantic</span> <span class="token keyword">class</span> <span class="token class-name">Item</span> <span class="token punctuation">(</span> BaseModel <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token comment"># kế thừa từ class Basemodel và khai báo các biến</span> name <span class="token punctuation">:</span> <span class="token builtin">str</span> description <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">str</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> price <span class="token punctuation">:</span> <span class="token builtin">float</span> tax <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">float</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> app <span class="token operator">=</span> FastAPI <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token decorator annotation punctuation">@app <span class="token punctuation">.</span> post</span> <span class="token punctuation">(</span> <span class="token string">"/items/"</span> <span class="token punctuation">)</span> <span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">create_item</span> <span class="token punctuation">(</span> item <span class="token punctuation">:</span> Item <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token comment"># khai báo dưới dạng parameter</span> <span class="token keyword">return</span> item |
Example of an instance of Item class.
1 2 3 4 5 6 7 | { "name": "Foo", "description": "An optional description", "price": 45.2, "tax": 3.5 } |
Since the description
and tax
have the value None, you may not need to add them.
1 2 3 4 5 | { "name": "Foo", "price": 45.2 } |
Based on the import of the Pydantic module, FastAPI supports:
- Read request body as Json.
- Convert variable format.
- Validate data
- Declare the default format of the request body, the Item class above is an example.
- Gen JSON Schema for your model
- Schema will be genetically transformed into UI of OpenAI doc.
Use model
In the create_item function, you can customize the Item class variables, as simple as calculating the taxable fee by calculating the sum of item.price
and item.tax
as shown below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <span class="token keyword">from</span> typing <span class="token keyword">import</span> Optional <span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI <span class="token keyword">from</span> pydantic <span class="token keyword">import</span> BaseModel <span class="token keyword">class</span> <span class="token class-name">Item</span> <span class="token punctuation">(</span> BaseModel <span class="token punctuation">)</span> <span class="token punctuation">:</span> name <span class="token punctuation">:</span> <span class="token builtin">str</span> description <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">str</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> price <span class="token punctuation">:</span> <span class="token builtin">float</span> tax <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">float</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> app <span class="token operator">=</span> FastAPI <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token decorator annotation punctuation">@app <span class="token punctuation">.</span> post</span> <span class="token punctuation">(</span> <span class="token string">"/items/"</span> <span class="token punctuation">)</span> <span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">create_item</span> <span class="token punctuation">(</span> item <span class="token punctuation">:</span> Item <span class="token punctuation">)</span> <span class="token punctuation">:</span> item_dict <span class="token operator">=</span> item <span class="token punctuation">.</span> <span class="token builtin">dict</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">if</span> item <span class="token punctuation">.</span> tax <span class="token punctuation">:</span> price_with_tax <span class="token operator">=</span> item <span class="token punctuation">.</span> price <span class="token operator">+</span> item <span class="token punctuation">.</span> tax item_dict <span class="token punctuation">.</span> update <span class="token punctuation">(</span> <span class="token punctuation">{</span> <span class="token string">"price_with_tax"</span> <span class="token punctuation">:</span> price_with_tax <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> item_dict |
Request body + path parameters
FastAPI supports declaring URL parameters and request body at the same time, the framework will know which parameters pass from the path and which parameters are taken from the request.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <span class="token keyword">from</span> typing <span class="token keyword">import</span> Optional <span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI <span class="token keyword">from</span> pydantic <span class="token keyword">import</span> BaseModel <span class="token keyword">class</span> <span class="token class-name">Item</span> <span class="token punctuation">(</span> BaseModel <span class="token punctuation">)</span> <span class="token punctuation">:</span> name <span class="token punctuation">:</span> <span class="token builtin">str</span> description <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">str</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> price <span class="token punctuation">:</span> <span class="token builtin">float</span> tax <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">float</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> app <span class="token operator">=</span> FastAPI <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token decorator annotation punctuation">@app <span class="token punctuation">.</span> put</span> <span class="token punctuation">(</span> <span class="token string">"/items/{item_id}"</span> <span class="token punctuation">)</span> <span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">create_item</span> <span class="token punctuation">(</span> item_id <span class="token punctuation">:</span> <span class="token builtin">int</span> <span class="token punctuation">,</span> item <span class="token punctuation">:</span> Item <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token string">"item_id"</span> <span class="token punctuation">:</span> item_id <span class="token punctuation">,</span> <span class="token operator">**</span> item <span class="token punctuation">.</span> <span class="token builtin">dict</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
P / S: Similar to above, you can add URL parameter, query parameter and request body at the same time.
Query Parameters and String Validations
In the previous part, we already know the concept of query parameter, it’s okay to have one type of param. This parameter has an attribute of Optional
, but the length is limited to no more than 50 characters. So FastAPI provides Query class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | from typing import Optional from fastapi import FastAPI, Query app = FastAPI() @app.get("/items/") async def read_items(q: Optional[str] = Query(None, max_length=50)): results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} if q: results.update({"q": q}) return results |
The statement q: Optional[str] = Query(None)
is similar to q: Optional[str] = None
but Query provides other parameters like max_leht, min_leht, regex, … You can increase the character limit to 250 like this just changing the parameter value. (Default of max_lenght is 50)
1 2 | q: Optional[str] = Query(None, max_length=250) |
Query parameter list / multiple values
In addition to string and integer formats, FastAPI also supports List type.
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token keyword">from</span> typing <span class="token keyword">import</span> List <span class="token punctuation">,</span> Optional <span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI <span class="token punctuation">,</span> Query app <span class="token operator">=</span> FastAPI <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token decorator annotation punctuation">@app <span class="token punctuation">.</span> get</span> <span class="token punctuation">(</span> <span class="token string">"/items/"</span> <span class="token punctuation">)</span> <span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">read_items</span> <span class="token punctuation">(</span> q <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> List <span class="token punctuation">[</span> <span class="token builtin">str</span> <span class="token punctuation">]</span> <span class="token punctuation">]</span> <span class="token operator">=</span> Query <span class="token punctuation">(</span> <span class="token boolean">None</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">:</span> query_items <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token string">"q"</span> <span class="token punctuation">:</span> q <span class="token punctuation">}</span> <span class="token keyword">return</span> query_items |
1 2 3 | # q là 1 List có thể chứa nhiều giá trị. http://localhost:8000/items/?q=foo&q=bar |
Response body that the API returns.
1 2 3 4 5 6 7 | { "q": [ "foo", "bar" ] } |
The API is also updated as well.
P / S: You can also replace List[str]
to list
like this.
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI <span class="token punctuation">,</span> Query app <span class="token operator">=</span> FastAPI <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token decorator annotation punctuation">@app <span class="token punctuation">.</span> get</span> <span class="token punctuation">(</span> <span class="token string">"/items/"</span> <span class="token punctuation">)</span> <span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">read_items</span> <span class="token punctuation">(</span> q <span class="token punctuation">:</span> <span class="token builtin">list</span> <span class="token operator">=</span> Query <span class="token punctuation">(</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">:</span> query_items <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token string">"q"</span> <span class="token punctuation">:</span> q <span class="token punctuation">}</span> <span class="token keyword">return</span> query_items |
Query has a few more parameters, but not too important, you can go to the FastAPI doc to find out details.
The params that Query provides:
Metadata
alias
: other name of paramtitle
: metadata named paramdescription
: metadata introduces paramdeprecated
: when you are bored of any param, add it to let the user know that you are no longer using that param
Validation for string:
min_lenght
max_lenght
regex
Path Parameters and Numeric Validations
Query parameters have a Query class to declare metadata and validations, Path parameters have a Pass class with a similar mechanism.
Add title
metadata for path param item_id
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token keyword">from</span> typing <span class="token keyword">import</span> Optional <span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI <span class="token punctuation">,</span> Path <span class="token punctuation">,</span> Query app <span class="token operator">=</span> FastAPI <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token decorator annotation punctuation">@app <span class="token punctuation">.</span> get</span> <span class="token punctuation">(</span> <span class="token string">"/items/{item_id}"</span> <span class="token punctuation">)</span> <span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">read_items</span> <span class="token punctuation">(</span> item_id <span class="token punctuation">:</span> <span class="token builtin">int</span> <span class="token operator">=</span> Path <span class="token punctuation">(</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">,</span> title <span class="token operator">=</span> <span class="token string">"The ID of the item to get"</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> q <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">str</span> <span class="token punctuation">]</span> <span class="token operator">=</span> Query <span class="token punctuation">(</span> <span class="token boolean">None</span> <span class="token punctuation">,</span> alias <span class="token operator">=</span> <span class="token string">"item-query"</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> <span class="token punctuation">)</span> <span class="token punctuation">:</span> results <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token string">"item_id"</span> <span class="token punctuation">:</span> item_id <span class="token punctuation">}</span> <span class="token keyword">if</span> q <span class="token punctuation">:</span> results <span class="token punctuation">.</span> update <span class="token punctuation">(</span> <span class="token punctuation">{</span> <span class="token string">"q"</span> <span class="token punctuation">:</span> q <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> results |
Number validations: greater than or equal
We can not only validate strings, but also numbers.
With param ge=1
of the Path class, item_id
must be a number greater than or equal to 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI <span class="token punctuation">,</span> Path app <span class="token operator">=</span> FastAPI <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token decorator annotation punctuation">@app <span class="token punctuation">.</span> get</span> <span class="token punctuation">(</span> <span class="token string">"/items/{item_id}"</span> <span class="token punctuation">)</span> <span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">read_items</span> <span class="token punctuation">(</span> <span class="token operator">*</span> <span class="token punctuation">,</span> item_id <span class="token punctuation">:</span> <span class="token builtin">int</span> <span class="token operator">=</span> Path <span class="token punctuation">(</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">,</span> title <span class="token operator">=</span> <span class="token string">"The ID of the item to get"</span> <span class="token punctuation">,</span> ge <span class="token operator">=</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> q <span class="token punctuation">:</span> <span class="token builtin">str</span> <span class="token punctuation">)</span> <span class="token punctuation">:</span> results <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token string">"item_id"</span> <span class="token punctuation">:</span> item_id <span class="token punctuation">}</span> <span class="token keyword">if</span> q <span class="token punctuation">:</span> results <span class="token punctuation">.</span> update <span class="token punctuation">(</span> <span class="token punctuation">{</span> <span class="token string">"q"</span> <span class="token punctuation">:</span> q <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> results |
Number validations: greater than and less than or equal
Similar to le=100
, item_id
must be a number less than or equal to 100.
1 2 | item_id: int = Path(..., title="The ID of the item to get", gt=0, le=1000) |
P / S: Number validations not only supports type integer, but also support for type float.
1 2 | size: float = Query(..., gt=0, lt=10.5) |
gt
: > gt >ge
: ≥ ge ≥lt
: < lt <le
: ≤ le ≤
Body
Multiple Parameters
Simply, FastAPI supports creating formats for the request body, you can use not only 1 but the N Pydantic model as in the example below, I declare 2 Item
classes and User
classes, respectively, 2 Pydantic models.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <span class="token keyword">from</span> typing <span class="token keyword">import</span> Optional <span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI <span class="token keyword">from</span> pydantic <span class="token keyword">import</span> BaseModel app <span class="token operator">=</span> FastAPI <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">class</span> <span class="token class-name">Item</span> <span class="token punctuation">(</span> BaseModel <span class="token punctuation">)</span> <span class="token punctuation">:</span> name <span class="token punctuation">:</span> <span class="token builtin">str</span> description <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">str</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> price <span class="token punctuation">:</span> <span class="token builtin">float</span> tax <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">float</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> <span class="token keyword">class</span> <span class="token class-name">User</span> <span class="token punctuation">(</span> BaseModel <span class="token punctuation">)</span> <span class="token punctuation">:</span> username <span class="token punctuation">:</span> <span class="token builtin">str</span> full_name <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">str</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> <span class="token decorator annotation punctuation">@app <span class="token punctuation">.</span> put</span> <span class="token punctuation">(</span> <span class="token string">"/items/{item_id}"</span> <span class="token punctuation">)</span> <span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">update_item</span> <span class="token punctuation">(</span> item_id <span class="token punctuation">:</span> <span class="token builtin">int</span> <span class="token punctuation">,</span> item <span class="token punctuation">:</span> Item <span class="token punctuation">,</span> user <span class="token punctuation">:</span> User <span class="token punctuation">)</span> <span class="token punctuation">:</span> results <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token string">"item_id"</span> <span class="token punctuation">:</span> item_id <span class="token punctuation">,</span> <span class="token string">"item"</span> <span class="token punctuation">:</span> item <span class="token punctuation">,</span> <span class="token string">"user"</span> <span class="token punctuation">:</span> user <span class="token punctuation">}</span> <span class="token keyword">return</span> results |
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token punctuation">{</span> <span class="token string">"item"</span> <span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token string">"name"</span> <span class="token punctuation">:</span> <span class="token string">"Foo"</span> <span class="token punctuation">,</span> <span class="token string">"description"</span> <span class="token punctuation">:</span> <span class="token string">"The pretender"</span> <span class="token punctuation">,</span> <span class="token string">"price"</span> <span class="token punctuation">:</span> <span class="token number">42.0</span> <span class="token punctuation">,</span> <span class="token string">"tax"</span> <span class="token punctuation">:</span> <span class="token number">3.2</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token string">"user"</span> <span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token string">"username"</span> <span class="token punctuation">:</span> <span class="token string">"Hoang"</span> <span class="token punctuation">,</span> <span class="token string">"full_name"</span> <span class="token punctuation">:</span> <span class="token string">"Hoang Pham"</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Singular values in body
You can also add define a body for only 1 value without declaring the class, for example here I add an importance
param with type int and also a key located in json body, so when you post data, you must also declare values for importance
.
1 2 3 4 | <span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">update_item</span> <span class="token punctuation">(</span> item_id <span class="token punctuation">:</span> <span class="token builtin">int</span> <span class="token punctuation">,</span> item <span class="token punctuation">:</span> Item <span class="token punctuation">,</span> user <span class="token punctuation">:</span> User <span class="token punctuation">,</span> importance <span class="token punctuation">:</span> <span class="token builtin">int</span> <span class="token operator">=</span> Body <span class="token punctuation">(</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">:</span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <span class="token punctuation">{</span> <span class="token string">"item"</span> <span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token string">"name"</span> <span class="token punctuation">:</span> <span class="token string">"Foo"</span> <span class="token punctuation">,</span> <span class="token string">"description"</span> <span class="token punctuation">:</span> <span class="token string">"The pretender"</span> <span class="token punctuation">,</span> <span class="token string">"price"</span> <span class="token punctuation">:</span> <span class="token number">42.0</span> <span class="token punctuation">,</span> <span class="token string">"tax"</span> <span class="token punctuation">:</span> <span class="token number">3.2</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token string">"user"</span> <span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token string">"username"</span> <span class="token punctuation">:</span> <span class="token string">"Hoang"</span> <span class="token punctuation">,</span> <span class="token string">"full_name"</span> <span class="token punctuation">:</span> <span class="token string">"Hoang Pham"</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token string">"importance"</span> <span class="token punctuation">:</span> <span class="token number">5</span> <span class="token punctuation">}</span> |
Multiple body params and query
Simply put, it combines multiple body param with the query param.
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">update_item</span> <span class="token punctuation">(</span> <span class="token operator">*</span> <span class="token punctuation">,</span> item_id <span class="token punctuation">:</span> <span class="token builtin">int</span> <span class="token punctuation">,</span> item <span class="token punctuation">:</span> Item <span class="token punctuation">,</span> user <span class="token punctuation">:</span> User <span class="token punctuation">,</span> importance <span class="token punctuation">:</span> <span class="token builtin">int</span> <span class="token operator">=</span> Body <span class="token punctuation">(</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">,</span> gt <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> q <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">str</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> <span class="token punctuation">)</span> <span class="token punctuation">:</span> results <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token string">"item_id"</span> <span class="token punctuation">:</span> item_id <span class="token punctuation">,</span> <span class="token string">"item"</span> <span class="token punctuation">:</span> item <span class="token punctuation">,</span> <span class="token string">"user"</span> <span class="token punctuation">:</span> user <span class="token punctuation">,</span> <span class="token string">"importance"</span> <span class="token punctuation">:</span> importance <span class="token punctuation">}</span> <span class="token keyword">if</span> q <span class="token punctuation">:</span> results <span class="token punctuation">.</span> update <span class="token punctuation">(</span> <span class="token punctuation">{</span> <span class="token string">"q"</span> <span class="token punctuation">:</span> q <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> results |
Field
To validate data or add metadata in a class say Item
for example, you need to import the Field
operation function from the pydantic
module.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <span class="token keyword">from</span> typing <span class="token keyword">import</span> Optional <span class="token keyword">from</span> fastapi <span class="token keyword">import</span> Body <span class="token punctuation">,</span> FastAPI <span class="token keyword">from</span> pydantic <span class="token keyword">import</span> BaseModel <span class="token punctuation">,</span> Field app <span class="token operator">=</span> FastAPI <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">class</span> <span class="token class-name">Item</span> <span class="token punctuation">(</span> BaseModel <span class="token punctuation">)</span> <span class="token punctuation">:</span> name <span class="token punctuation">:</span> <span class="token builtin">str</span> description <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">str</span> <span class="token punctuation">]</span> <span class="token operator">=</span> Field <span class="token punctuation">(</span> <span class="token boolean">None</span> <span class="token punctuation">,</span> title <span class="token operator">=</span> <span class="token string">"The description of the item"</span> <span class="token punctuation">,</span> max_length <span class="token operator">=</span> <span class="token number">300</span> <span class="token punctuation">)</span> price <span class="token punctuation">:</span> <span class="token builtin">float</span> <span class="token operator">=</span> Field <span class="token punctuation">(</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">,</span> gt <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">,</span> description <span class="token operator">=</span> <span class="token string">"The price must be greater than zero"</span> <span class="token punctuation">)</span> tax <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">float</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> <span class="token decorator annotation punctuation">@app <span class="token punctuation">.</span> put</span> <span class="token punctuation">(</span> <span class="token string">"/items/{item_id}"</span> <span class="token punctuation">)</span> <span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">update_item</span> <span class="token punctuation">(</span> item_id <span class="token punctuation">:</span> <span class="token builtin">int</span> <span class="token punctuation">,</span> item <span class="token punctuation">:</span> Item <span class="token operator">=</span> Body <span class="token punctuation">(</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">,</span> embed <span class="token operator">=</span> <span class="token boolean">True</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">:</span> results <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token string">"item_id"</span> <span class="token punctuation">:</span> item_id <span class="token punctuation">,</span> <span class="token string">"item"</span> <span class="token punctuation">:</span> item <span class="token punctuation">}</span> <span class="token keyword">return</span> results |
As the above code, param description
has metadata title, length does not exceed 300 words, or as param price
not be less than 0 and has metadata as description.
Nested Models
In addition to the types int, float, and str, you can also add a list or set type as shown below.
1 2 3 4 5 6 7 | <span class="token keyword">class</span> <span class="token class-name">Item</span> <span class="token punctuation">(</span> BaseModel <span class="token punctuation">)</span> <span class="token punctuation">:</span> name <span class="token punctuation">:</span> <span class="token builtin">str</span> description <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">str</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> price <span class="token punctuation">:</span> <span class="token builtin">float</span> tax <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">float</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> tags <span class="token punctuation">:</span> <span class="token builtin">list</span> <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> |
With the above declaration, when you pass the param is 1 list, but with the above declaration, this list will not determine the format of each element in the list. That’s okay because Python has a List
module that supports you to declare a param as a list that determines the format of each element.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token keyword">from</span> typing <span class="token keyword">import</span> List <span class="token punctuation">,</span> Optional <span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI <span class="token keyword">from</span> pydantic <span class="token keyword">import</span> BaseModel app <span class="token operator">=</span> FastAPI <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">class</span> <span class="token class-name">Item</span> <span class="token punctuation">(</span> BaseModel <span class="token punctuation">)</span> <span class="token punctuation">:</span> name <span class="token punctuation">:</span> <span class="token builtin">str</span> description <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">str</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> price <span class="token punctuation">:</span> <span class="token builtin">float</span> tax <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">float</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> tags <span class="token punctuation">:</span> List <span class="token punctuation">[</span> <span class="token builtin">str</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> |
Similar to List
, you can add Set
.
1 2 3 4 5 6 7 8 9 | <span class="token keyword">from</span> typing <span class="token keyword">import</span> Optional <span class="token punctuation">,</span> Set <span class="token keyword">class</span> <span class="token class-name">Item</span> <span class="token punctuation">(</span> BaseModel <span class="token punctuation">)</span> <span class="token punctuation">:</span> name <span class="token punctuation">:</span> <span class="token builtin">str</span> description <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">str</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> price <span class="token punctuation">:</span> <span class="token builtin">float</span> tax <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">float</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> tags <span class="token punctuation">:</span> Set <span class="token punctuation">[</span> <span class="token builtin">str</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token builtin">set</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> |
In addition, normal types such as str, int, float, … FastAPI also supports more complex and diverse formats, assuming the HttpUrl
format inherits from str
. For more information please check this link ( https://pydantic-docs.helpmanual.io/usage/types/ ).
- Next, I will introduce you how to declare a model nested in another model.
Let’s say I have 2 classes Images and Item.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <span class="token keyword">from</span> typing <span class="token keyword">import</span> Optional <span class="token punctuation">,</span> Set <span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI <span class="token keyword">from</span> pydantic <span class="token keyword">import</span> BaseModel app <span class="token operator">=</span> FastAPI <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">class</span> <span class="token class-name">Image</span> <span class="token punctuation">(</span> BaseModel <span class="token punctuation">)</span> <span class="token punctuation">:</span> url <span class="token punctuation">:</span> <span class="token builtin">str</span> name <span class="token punctuation">:</span> <span class="token builtin">str</span> <span class="token keyword">class</span> <span class="token class-name">Item</span> <span class="token punctuation">(</span> BaseModel <span class="token punctuation">)</span> <span class="token punctuation">:</span> name <span class="token punctuation">:</span> <span class="token builtin">str</span> description <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">str</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> price <span class="token punctuation">:</span> <span class="token builtin">float</span> tax <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">float</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> tags <span class="token punctuation">:</span> Set <span class="token punctuation">[</span> <span class="token builtin">str</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> |
I want the Images class to be in Item class like this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <span class="token punctuation">{</span> <span class="token string">"item"</span> <span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token string">"name"</span> <span class="token punctuation">:</span> <span class="token string">"Foo"</span> <span class="token punctuation">,</span> <span class="token string">"description"</span> <span class="token punctuation">:</span> <span class="token string">"The pretender"</span> <span class="token punctuation">,</span> <span class="token string">"price"</span> <span class="token punctuation">:</span> <span class="token number">42.0</span> <span class="token punctuation">,</span> <span class="token string">"tax"</span> <span class="token punctuation">:</span> <span class="token number">3.2</span> <span class="token punctuation">,</span> <span class="token string">"tags"</span> <span class="token punctuation">:</span> <span class="token punctuation">[</span> <span class="token string">"rock"</span> <span class="token punctuation">,</span> <span class="token string">"metal"</span> <span class="token punctuation">,</span> <span class="token string">"bar"</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> <span class="token string">"image"</span> <span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token string">"url"</span> <span class="token punctuation">:</span> <span class="token string">"http://example.com/baz.jpg"</span> <span class="token punctuation">,</span> <span class="token string">"name"</span> <span class="token punctuation">:</span> <span class="token string">"The Foo live"</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
You just need to add 1 line of code to the Item class. Easy!
1 2 3 4 5 6 7 8 | <span class="token keyword">class</span> <span class="token class-name">Item</span> <span class="token punctuation">(</span> BaseModel <span class="token punctuation">)</span> <span class="token punctuation">:</span> name <span class="token punctuation">:</span> <span class="token builtin">str</span> description <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">str</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> price <span class="token punctuation">:</span> <span class="token builtin">float</span> tax <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">float</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> tags <span class="token punctuation">:</span> Set <span class="token punctuation">[</span> <span class="token builtin">str</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> image <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> Image <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> |
You can also customize the format of Pydantic models to be list or set, for example.
1 2 | images <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> List <span class="token punctuation">[</span> Image <span class="token punctuation">]</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> |
And this is the result.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <span class="token punctuation">{</span> <span class="token string">"name"</span> <span class="token punctuation">:</span> <span class="token string">"Foo"</span> <span class="token punctuation">,</span> <span class="token string">"description"</span> <span class="token punctuation">:</span> <span class="token string">"The pretender"</span> <span class="token punctuation">,</span> <span class="token string">"price"</span> <span class="token punctuation">:</span> <span class="token number">42.0</span> <span class="token punctuation">,</span> <span class="token string">"tax"</span> <span class="token punctuation">:</span> <span class="token number">3.2</span> <span class="token punctuation">,</span> <span class="token string">"tags"</span> <span class="token punctuation">:</span> <span class="token punctuation">[</span> <span class="token string">"rock"</span> <span class="token punctuation">,</span> <span class="token string">"metal"</span> <span class="token punctuation">,</span> <span class="token string">"bar"</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> <span class="token string">"images"</span> <span class="token punctuation">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> <span class="token string">"url"</span> <span class="token punctuation">:</span> <span class="token string">"http://example.com/baz.jpg"</span> <span class="token punctuation">,</span> <span class="token string">"name"</span> <span class="token punctuation">:</span> <span class="token string">"The Foo live"</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token string">"url"</span> <span class="token punctuation">:</span> <span class="token string">"http://example.com/dave.jpg"</span> <span class="token punctuation">,</span> <span class="token string">"name"</span> <span class="token punctuation">:</span> <span class="token string">"The Baz"</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span> |
In theory you could repeat the nested models as follows. The Image class is in the Item class, while the Item class is in the Offer class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <span class="token keyword">from</span> typing <span class="token keyword">import</span> List <span class="token punctuation">,</span> Optional <span class="token punctuation">,</span> Set <span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI <span class="token punctuation">,</span> Body <span class="token keyword">from</span> pydantic <span class="token keyword">import</span> BaseModel <span class="token punctuation">,</span> HttpUrl app <span class="token operator">=</span> FastAPI <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">class</span> <span class="token class-name">Image</span> <span class="token punctuation">(</span> BaseModel <span class="token punctuation">)</span> <span class="token punctuation">:</span> url <span class="token punctuation">:</span> HttpUrl name <span class="token punctuation">:</span> <span class="token builtin">str</span> <span class="token keyword">class</span> <span class="token class-name">Item</span> <span class="token punctuation">(</span> BaseModel <span class="token punctuation">)</span> <span class="token punctuation">:</span> name <span class="token punctuation">:</span> <span class="token builtin">str</span> description <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">str</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> price <span class="token punctuation">:</span> <span class="token builtin">float</span> tax <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">float</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> tags <span class="token punctuation">:</span> Set <span class="token punctuation">[</span> <span class="token builtin">str</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> images <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> List <span class="token punctuation">[</span> Image <span class="token punctuation">]</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> <span class="token keyword">class</span> <span class="token class-name">Offer</span> <span class="token punctuation">(</span> BaseModel <span class="token punctuation">)</span> <span class="token punctuation">:</span> name <span class="token punctuation">:</span> <span class="token builtin">str</span> description <span class="token punctuation">:</span> Optional <span class="token punctuation">[</span> <span class="token builtin">str</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">None</span> price <span class="token punctuation">:</span> <span class="token builtin">float</span> items <span class="token punctuation">:</span> List <span class="token punctuation">[</span> Item <span class="token punctuation">]</span> <span class="token decorator annotation punctuation">@app <span class="token punctuation">.</span> post</span> <span class="token punctuation">(</span> <span class="token string">"/offers/"</span> <span class="token punctuation">)</span> <span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">create_offer</span> <span class="token punctuation">(</span> offer <span class="token punctuation">:</span> Offer <span class="token operator">=</span> Body <span class="token punctuation">(</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">,</span> embed <span class="token operator">=</span> <span class="token boolean">True</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token keyword">return</span> offer |
Conclude
Since FastAPI is a new API framework with a lot of features, I split it up into several parts (basically due to not being patient enough to write). Here I will only list the important features that are used a lot first and then advance in the next sections. You can also check it directly on the doc by fastapi. Link refer here: