Fast Api [part 1 ]
Tags: python, devjournal, tutorial
Published: 2022-03-31 15:46:36

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.
![fast](https://media.giphy.com/media/3ornjIhZGFWpbcGMAU/giphy.gif)


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 <mark>Pipfile</mark> and <mark>Pipfile.lock</mark> 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.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nb25qqg2vvnifk7eug7n.PNG)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4q2xsbxuh3rtl8sv6gml.PNG)
 

We need `uvicorn` to start our server. [source](https://www.uvicorn.org/)
`pipenv install uvicorn[standard]`

---

##### Basic app setup
Now lets build a server.

```python
from fastapi import FastAPI

app = FastAPI()


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

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

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4cmosvlt59x8v94cdv21.png)

2) Select the python interpreter that matches your project name
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ot1cg3ec7yg9n4d91ose.png)
 
We no longer have any warnings.
Then we launch our app by issuing the following command. 
`uvicorn main:app --reload`

The <mark>--reload</mark>: make the server restart after code changes. 

Note ⚠️: Only use for development.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4bd7821bb94043oktnvj.PNG)


---

##### 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

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cymy5haiq19r5qqgf4id.PNG)

We got our JSON response.


---


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

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/80877io0mxll81nlg1n6.PNG)

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

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x7247ejxujnj67vmt25w.PNG)


---


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`
 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/062kuz301nykrf276v6q.PNG)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dfoh00j8692q0qsae319.PNG)


---

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

```python
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
```

When you execute, you get:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mlc7nmh64gwa19nivq1s.PNG)


---
 

Next, we create a post request using BaseModel from pydantic

```python
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} 
```

Now let's test our create_person endpoint using the swagger docs
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dadey8lg7i1koc8ietmt.PNG)

When you click on execute you get:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vpxcn9p2kf3s0dmbhggy.PNG)


---

  
##### Let's perform methods on our pydantic model.
- change our name to uppercase
- use string formatting to output our result
 
```python
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"}

```
Result:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ns6h56gurfqnmjuom4ed.PNG)
 
---

##### 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.

```python
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
```
Here we entered the name, age and tall 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ih08ps4ldkdfyb571zjd.PNG)

But our server responds with the name only
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qn0psanj042lcngzpr6h.PNG)
  
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](https://fastapi.tiangolo.com/tutorial/first-steps/)
[Uvicorn](https://www.uvicorn.org/)