Fast Api [part 1 ]

Hello there, today we’ll look at how to use Fast APi to develop a rest API. It allows you to quickly construct APIs with minimal code.

Prerequisite to follow along

Python installed
Pipenv Virtual Environment
Vscode

Install pipenv

pip install --user pipenv


Following along requires the following prerequisites:

Install fastapi
pipenv install fastapi
This creates Pipfile and Pipfile.lock files in your project directory. Think of these like our package.json and package.lock.json files in Nodejs. The pipfile holds our project dependencies.

We need uvicorn to start our server. source
pipenv install uvicorn[standard]


Basic app setup

Now lets build a server.

<span>from</span> <span>fastapi</span> <span>import</span> <span>FastAPI</span>
<span>app</span> <span>=</span> <span>FastAPI</span><span>()</span>
<span>@app.get</span><span>(</span><span>"</span><span>/</span><span>"</span><span>)</span>
<span>async</span> <span>def</span> <span>root</span><span>():</span>
<span>return</span> <span>{</span><span>"</span><span>message</span><span>"</span><span>:</span> <span>"</span><span>Hello World</span><span>"</span><span>}</span>
<span>from</span> <span>fastapi</span> <span>import</span> <span>FastAPI</span>

<span>app</span> <span>=</span> <span>FastAPI</span><span>()</span>


<span>@app.get</span><span>(</span><span>"</span><span>/</span><span>"</span><span>)</span>
<span>async</span> <span>def</span> <span>root</span><span>():</span>
    <span>return</span> <span>{</span><span>"</span><span>message</span><span>"</span><span>:</span> <span>"</span><span>Hello World</span><span>"</span><span>}</span>
from fastapi import FastAPI app = FastAPI() @app.get("/") async def root(): return {"message": "Hello World"}

Enter fullscreen mode Exit fullscreen mode

The above is the most basic version of our restapi.
We now have a problem because we use vscode and our Python interpreter cannot be found.


Fixing import "fastapi" could not be resolved

1) Press Ctrl + Shift + P on your VsCode

2) Select the python interpreter that matches your project name

We no longer have any warnings.
Then we launch our app by issuing the following command.
uvicorn main:app --reload

The –reload: make the server restart after code changes.

Note ️: Only use for development.


Testing our api

Lets visit our browser to at the host and port given to us when we ran the uvicorn command. Open your browser at http://127.0.0.1:8000

We got our JSON response.


Let’s create another endpoint that outputs a list of dictionary, like an array of object in JavaScript.

Now lets visit our browser http://127.0.0.1:8000/persons


The beauty of FastApi is that it comes preloaded with a documentation engine called Swagger.

We go to get the documentation for the two endpoints (also called path operation decorator) we mentioned earlier by visiting http://127.0.0.1:8000/docs


Before working with BaseModel from pydantic, let’s another way we can return contents e.g a dictionary of cars

<span>from</span> <span>fastapi</span> <span>import</span> <span>FastAPI</span>
<span>from</span> <span>pydantic</span> <span>import</span> <span>BaseModel</span>
<span>app</span> <span>=</span> <span>FastAPI</span><span>()</span>
<span>cars</span> <span>=</span> <span>{</span>
<span>1</span><span>:{</span><span>"</span><span>model</span><span>"</span><span>:</span> <span>"</span><span>Volvo</span><span>"</span><span>,</span> <span>"</span><span>year</span><span>"</span><span>:</span> <span>2021</span><span>,</span> <span>"</span><span>new</span><span>"</span><span>:</span> <span>True</span><span>},</span>
<span>2</span><span>:{</span><span>"</span><span>model</span><span>"</span><span>:</span> <span>"</span><span>Benz</span><span>"</span><span>,</span> <span>"</span><span>year</span><span>"</span><span>:</span><span>2020</span><span>},</span>
<span>3</span><span>:{</span><span>"</span><span>model</span><span>"</span><span>:</span> <span>"</span><span>Toyota</span><span>"</span><span>,</span> <span>"</span><span>year</span><span>"</span><span>:</span> <span>1999</span><span>},</span>
<span>}</span>
<span>@app.get</span><span>(</span><span>"</span><span>/cars</span><span>"</span><span>)</span>
<span>async</span> <span>def</span> <span>show_cars</span><span>():</span>
<span>return</span> <span>cars</span>
<span>from</span> <span>fastapi</span> <span>import</span> <span>FastAPI</span>
<span>from</span> <span>pydantic</span> <span>import</span> <span>BaseModel</span>

<span>app</span> <span>=</span> <span>FastAPI</span><span>()</span>


<span>cars</span> <span>=</span> <span>{</span>
     <span>1</span><span>:{</span><span>"</span><span>model</span><span>"</span><span>:</span> <span>"</span><span>Volvo</span><span>"</span><span>,</span> <span>"</span><span>year</span><span>"</span><span>:</span> <span>2021</span><span>,</span> <span>"</span><span>new</span><span>"</span><span>:</span> <span>True</span><span>},</span>
     <span>2</span><span>:{</span><span>"</span><span>model</span><span>"</span><span>:</span> <span>"</span><span>Benz</span><span>"</span><span>,</span> <span>"</span><span>year</span><span>"</span><span>:</span><span>2020</span><span>},</span>
     <span>3</span><span>:{</span><span>"</span><span>model</span><span>"</span><span>:</span> <span>"</span><span>Toyota</span><span>"</span><span>,</span> <span>"</span><span>year</span><span>"</span><span>:</span> <span>1999</span><span>},</span>
<span>}</span>


<span>@app.get</span><span>(</span><span>"</span><span>/cars</span><span>"</span><span>)</span>
<span>async</span> <span>def</span> <span>show_cars</span><span>():</span>
    <span>return</span>  <span>cars</span>
from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() cars = { 1:{"model": "Volvo", "year": 2021, "new": True}, 2:{"model": "Benz", "year":2020}, 3:{"model": "Toyota", "year": 1999}, } @app.get("/cars") async def show_cars(): return cars

Enter fullscreen mode Exit fullscreen mode

When you execute, you get:


Next, we create a post request using BaseModel from pydantic

<span>from</span> <span>typing</span> <span>import</span> <span>Optional</span>
<span>from</span> <span>fastapi</span> <span>import</span> <span>FastAPI</span>
<span>from</span> <span>pydantic</span> <span>import</span> <span>BaseModel</span>
<span>app</span> <span>=</span> <span>FastAPI</span><span>()</span>
<span>@app.get</span><span>(</span><span>"</span><span>/</span><span>"</span><span>)</span>
<span>async</span> <span>def</span> <span>root</span><span>():</span>
<span>return</span> <span>{</span><span>"</span><span>message</span><span>"</span><span>:</span> <span>"</span><span>Hello World</span><span>"</span><span>}</span>
<span>@app.get</span><span>(</span><span>"</span><span>/persons</span><span>"</span><span>)</span>
<span>async</span> <span>def</span> <span>persons</span><span>():</span>
<span>return</span> <span>{</span><span>"</span><span>data</span><span>"</span><span>:</span> <span>[</span>
<span>{</span><span>"</span><span>name</span><span>"</span><span>:</span> <span>"</span><span>John</span><span>"</span><span>,</span> <span>"</span><span>age</span><span>"</span><span>:</span> <span>30</span><span>,</span> <span>"</span><span>tall</span><span>"</span><span>:</span> <span>True</span><span>},</span>
<span>{</span><span>"</span><span>name</span><span>"</span><span>:</span> <span>"</span><span>Doe</span><span>"</span><span>,</span> <span>"</span><span>age</span><span>"</span><span>:</span> <span>25</span><span>}</span>
<span>]}</span>
<span>class</span> <span>Person</span><span>(</span><span>BaseModel</span><span>):</span>
<span>name</span><span>:</span> <span>str</span>
<span>age</span><span>:</span> <span>int</span> <span>|</span> <span>None</span> <span>=</span> <span>None</span>
<span>tall</span><span>:</span> <span>bool</span> <span>=</span> <span>False</span>
<span>@app.post</span><span>(</span><span>"</span><span>/persons</span><span>"</span><span>)</span>
<span>async</span> <span>def</span> <span>create_person</span><span>(</span><span>person</span><span>:</span> <span>Person</span><span>):</span>
<span>return</span> <span>{</span><span>"</span><span>data</span><span>"</span><span>:</span> <span>person</span><span>}</span>
<span>from</span> <span>typing</span> <span>import</span> <span>Optional</span>
<span>from</span> <span>fastapi</span> <span>import</span> <span>FastAPI</span>
<span>from</span> <span>pydantic</span> <span>import</span> <span>BaseModel</span>

<span>app</span> <span>=</span> <span>FastAPI</span><span>()</span>


<span>@app.get</span><span>(</span><span>"</span><span>/</span><span>"</span><span>)</span>
<span>async</span> <span>def</span> <span>root</span><span>():</span>
    <span>return</span> <span>{</span><span>"</span><span>message</span><span>"</span><span>:</span> <span>"</span><span>Hello World</span><span>"</span><span>}</span>



<span>@app.get</span><span>(</span><span>"</span><span>/persons</span><span>"</span><span>)</span>
<span>async</span> <span>def</span> <span>persons</span><span>():</span>
    <span>return</span> <span>{</span><span>"</span><span>data</span><span>"</span><span>:</span> <span>[</span>
                        <span>{</span><span>"</span><span>name</span><span>"</span><span>:</span> <span>"</span><span>John</span><span>"</span><span>,</span> <span>"</span><span>age</span><span>"</span><span>:</span> <span>30</span><span>,</span> <span>"</span><span>tall</span><span>"</span><span>:</span> <span>True</span><span>},</span>
                        <span>{</span><span>"</span><span>name</span><span>"</span><span>:</span> <span>"</span><span>Doe</span><span>"</span><span>,</span> <span>"</span><span>age</span><span>"</span><span>:</span> <span>25</span><span>}</span>
                    <span>]}</span>

<span>class</span> <span>Person</span><span>(</span><span>BaseModel</span><span>):</span>
    <span>name</span><span>:</span> <span>str</span>
    <span>age</span><span>:</span> <span>int</span> <span>|</span> <span>None</span> <span>=</span> <span>None</span>
    <span>tall</span><span>:</span> <span>bool</span> <span>=</span> <span>False</span>

<span>@app.post</span><span>(</span><span>"</span><span>/persons</span><span>"</span><span>)</span>
<span>async</span> <span>def</span> <span>create_person</span><span>(</span><span>person</span><span>:</span> <span>Person</span><span>):</span>
    <span>return</span> <span>{</span><span>"</span><span>data</span><span>"</span><span>:</span> <span>person</span><span>}</span> 
from typing import Optional from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() @app.get("/") async def root(): return {"message": "Hello World"} @app.get("/persons") async def persons(): return {"data": [ {"name": "John", "age": 30, "tall": True}, {"name": "Doe", "age": 25} ]} class Person(BaseModel): name: str age: int | None = None tall: bool = False @app.post("/persons") async def create_person(person: Person): return {"data": person}

Enter fullscreen mode Exit fullscreen mode

Now let’s test our create_person endpoint using the swagger docs

When you click on execute you get:


Let’s perform methods on our pydantic model.
  • change our name to uppercase
  • use string formatting to output our result
<span>from</span> <span>typing</span> <span>import</span> <span>Optional</span>
<span>from</span> <span>fastapi</span> <span>import</span> <span>FastAPI</span>
<span>from</span> <span>pydantic</span> <span>import</span> <span>BaseModel</span>
<span>app</span> <span>=</span> <span>FastAPI</span><span>()</span>
<span>@app.get</span><span>(</span><span>"</span><span>/</span><span>"</span><span>)</span>
<span>async</span> <span>def</span> <span>root</span><span>():</span>
<span>return</span> <span>{</span><span>"</span><span>message</span><span>"</span><span>:</span> <span>"</span><span>Hello World</span><span>"</span><span>}</span>
<span>class</span> <span>Person</span><span>(</span><span>BaseModel</span><span>):</span>
<span>name</span><span>:</span> <span>str</span>
<span>age</span><span>:</span> <span>int</span> <span>|</span> <span>None</span> <span>=</span> <span>None</span>
<span>tall</span><span>:</span> <span>bool</span> <span>=</span> <span>False</span>
<span>@app.post</span><span>(</span><span>"</span><span>/persons</span><span>"</span><span>)</span>
<span>async</span> <span>def</span> <span>create_person</span><span>(</span><span>person</span><span>:</span> <span>Person</span><span>):</span>
<span>return</span> <span>{</span><span>"</span><span>data</span><span>"</span><span>:</span> <span>f</span><span>"</span><span>my name is </span><span>{</span><span>person</span><span>.</span><span>name</span><span>.</span><span>upper</span><span>()</span><span>}</span><span> and i am </span><span>{</span><span>person</span><span>.</span><span>age</span><span>}</span><span> years old</span><span>"</span><span>}</span>
<span>from</span> <span>typing</span> <span>import</span> <span>Optional</span>
<span>from</span> <span>fastapi</span> <span>import</span> <span>FastAPI</span>
<span>from</span> <span>pydantic</span> <span>import</span> <span>BaseModel</span>

<span>app</span> <span>=</span> <span>FastAPI</span><span>()</span>


<span>@app.get</span><span>(</span><span>"</span><span>/</span><span>"</span><span>)</span>
<span>async</span> <span>def</span> <span>root</span><span>():</span>
    <span>return</span> <span>{</span><span>"</span><span>message</span><span>"</span><span>:</span> <span>"</span><span>Hello World</span><span>"</span><span>}</span>


<span>class</span> <span>Person</span><span>(</span><span>BaseModel</span><span>):</span>
    <span>name</span><span>:</span> <span>str</span>
    <span>age</span><span>:</span> <span>int</span> <span>|</span> <span>None</span> <span>=</span> <span>None</span>
    <span>tall</span><span>:</span> <span>bool</span> <span>=</span> <span>False</span>

<span>@app.post</span><span>(</span><span>"</span><span>/persons</span><span>"</span><span>)</span>
<span>async</span> <span>def</span> <span>create_person</span><span>(</span><span>person</span><span>:</span> <span>Person</span><span>):</span>
    <span>return</span> <span>{</span><span>"</span><span>data</span><span>"</span><span>:</span> <span>f</span><span>"</span><span>my name is </span><span>{</span><span>person</span><span>.</span><span>name</span><span>.</span><span>upper</span><span>()</span><span>}</span><span> and i am </span><span>{</span><span>person</span><span>.</span><span>age</span><span>}</span><span> years old</span><span>"</span><span>}</span>
from typing import Optional from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() @app.get("/") async def root(): return {"message": "Hello World"} class Person(BaseModel): name: str age: int | None = None tall: bool = False @app.post("/persons") async def create_person(person: Person): return {"data": f"my name is {person.name.upper()} and i am {person.age} years old"}

Enter fullscreen mode Exit fullscreen mode

Result:


Output model

Let’s create an output model. For example, lets assume on calling our endpoint we don’t want to show certain data to our client, we create another output model that hides certain data. In our case let’s hide our age and tall.

<span>from</span> <span>fastapi</span> <span>import</span> <span>FastAPI</span>
<span>from</span> <span>pydantic</span> <span>import</span> <span>BaseModel</span>
<span>app</span> <span>=</span> <span>FastAPI</span><span>()</span>
<span>@app.get</span><span>(</span><span>"</span><span>/</span><span>"</span><span>)</span>
<span>async</span> <span>def</span> <span>root</span><span>():</span>
<span>return</span> <span>{</span><span>"</span><span>message</span><span>"</span><span>:</span> <span>"</span><span>Hello World</span><span>"</span><span>}</span>
<span>class</span> <span>Person</span><span>(</span><span>BaseModel</span><span>):</span>
<span>name</span><span>:</span> <span>str</span>
<span>age</span><span>:</span> <span>int</span> <span>|</span> <span>None</span> <span>=</span> <span>None</span>
<span>tall</span><span>:</span> <span>bool</span> <span>|</span> <span>None</span> <span>=</span> <span>False</span>
<span>class</span> <span>PersonOutput</span><span>(</span><span>BaseModel</span><span>):</span>
<span>name</span><span>:</span> <span>str</span>
<span>@app.post</span><span>(</span><span>"</span><span>/persons</span><span>"</span><span>,</span> <span>response_model</span><span>=</span><span>PersonOutput</span><span>)</span>
<span>async</span> <span>def</span> <span>create_person</span><span>(</span><span>person</span><span>:</span> <span>Person</span><span>):</span>
<span>return</span> <span>person</span>
<span>from</span> <span>fastapi</span> <span>import</span> <span>FastAPI</span>
<span>from</span> <span>pydantic</span> <span>import</span> <span>BaseModel</span>

<span>app</span> <span>=</span> <span>FastAPI</span><span>()</span>


<span>@app.get</span><span>(</span><span>"</span><span>/</span><span>"</span><span>)</span>
<span>async</span> <span>def</span> <span>root</span><span>():</span>
    <span>return</span> <span>{</span><span>"</span><span>message</span><span>"</span><span>:</span> <span>"</span><span>Hello World</span><span>"</span><span>}</span>


<span>class</span> <span>Person</span><span>(</span><span>BaseModel</span><span>):</span>
    <span>name</span><span>:</span> <span>str</span>
    <span>age</span><span>:</span> <span>int</span> <span>|</span> <span>None</span> <span>=</span> <span>None</span>
    <span>tall</span><span>:</span> <span>bool</span> <span>|</span> <span>None</span> <span>=</span> <span>False</span> 

<span>class</span> <span>PersonOutput</span><span>(</span><span>BaseModel</span><span>):</span>
    <span>name</span><span>:</span> <span>str</span>

<span>@app.post</span><span>(</span><span>"</span><span>/persons</span><span>"</span><span>,</span> <span>response_model</span><span>=</span><span>PersonOutput</span><span>)</span>
<span>async</span> <span>def</span> <span>create_person</span><span>(</span><span>person</span><span>:</span> <span>Person</span><span>):</span>
    <span>return</span>  <span>person</span>
from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() @app.get("/") async def root(): return {"message": "Hello World"} class Person(BaseModel): name: str age: int | None = None tall: bool | None = False class PersonOutput(BaseModel): name: str @app.post("/persons", response_model=PersonOutput) async def create_person(person: Person): return person

Enter fullscreen mode Exit fullscreen mode

Here we entered the name, age and tall

But our server responds with the name only

If we test our api now, FastAPI will take care of filtering out all the data that is not declared in the output model (using Pydantic).


response_model_exclude_unset

Let’s learn how we can exclude

Conclusion

In a matter of minutes, we learned how to create a restapi using this modern Python framework, and we explored the swagger documentation that comes pre-installed with fast api.
In the following lesson, we’ll look at how to create full CRUD functionality against a sqlalchemy database, as well as error handling and status code.

I hope you found this post useful; thank you for taking the time to read it.

Resources

FastAPI
Uvicorn

原文链接:Fast Api [part 1 ]

© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享
Little compliments mean so much to me sometimes.
有时候,一点微不足道的肯定,对我却意义非凡
评论 抢沙发

请登录后发表评论

    暂无评论内容