# [Python] Developing an API with FastAPI

Hey, everyone! This is the first post of the series "API frameworks for Python". We are starting with the framework  [FastAPI](https://fastapi.tiangolo.com/). FastAPI is fast and really easy to use. Let's build a simple API to exemplify its use.

### 1. Install the library in your environment

````
pip install fastapi
````

We are going to need an ASGI to run it:

````
pip install uvicorn[standard]
````

### 2. Create the first endpoint

> main.py

````
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def hello_world():
    return {"message": "Hello world"}
````

### 3. Start the ASGI server

````
project-root$ uvicorn main:app --reload
````

If everything goes well, you can now access your app on [http://localhost:8000](http://localhost:8000) and see our hello world message.
You can access its documentation (swagger) on [http://localhost:8000/docs](http://localhost:8000/docs)

You have a second option of documentation and you can access it on [http://localhost:8000/redoc](http://localhost:8000/redoc)

FastAPI gets a bonus point for having Swagger and ReDoc configured by default.

### 4. Create the other verbs

We are going to create, update, find and list our resource. Another good thing about FastAPI is that it supports type hints, unlike Flask, that we have to write schemas for validation. So the model we are using here is going to be written with type hints and with Pydantic to perform the data validation.

> model.py

````
from pydantic import BaseModel
from typing import Optional


class School(BaseModel):
    id: Optional[int]
    name: str

````


** 4.1 Passing the request body ** 


We pass the request body as argument to the function, for example:

````
@app.post('/schools')
def save(school: School):
    # method implementation
    school.id = 1
    return school ````

Here we receive a school object.

Let's test this example:

````
curl -X POST -H "Content-Type: application/json" \
    -d '{"name": "new school"}' \
    http://localhost:8000/schools

>> {"id":1,"name":"new school"}
````

If we don't pass a required parameter or if we pass it as the wrong type, we receive a validation message:

````
curl -X POST -H "Content-Type: application/json"  \
-d '{"namef": "new school"}' \
http://localhost:8000/schools

>> {"detail":[{"loc":["body","name"],"msg":"field required","type":"value_error.missing"}]}r
````


** 4.2 Passing path params ** 

We pass the path params between {} in the url and we pass it as an argument to our function using the same name:

````
@app.get('/schools/{school_id}')
def find_by_id(school_id: int):
    # method implementation
    return {}

````



** 4.3 Passing query params **`

We denote the query param by using the keyword *Query*. The first parameter is the parameter's standard value.

````
@app.get('/schools')
def search(name: Optional[str] = Query('standard value', max_length=50)):
    # method implementation
    return {}

````

**4.4 Full example**

Here is how our full class would be like:

> main.py

````
from fastapi import FastAPI, Query
from model import School
from typing import Optional


app = FastAPI()


@app.post('/schools')
def save(school: School):
    # method implementation
    school.id = 1
    return school


@app.get('/schools')
def search(name: Optional[str] = Query(None, max_length=50)):
    # method implementation
    return {}


@app.get('/schools/{school_id}')
def find_by_id(school_id: int):
    # method implementation
    return {}


@app.patch('/schools/{school_id}/name')
def partial_update(name: str, school_id: int):
    # method implementation
    return {"message": "School updated"}


@app.put('/schools/{school_id}')
def update(school: School, school_id: int):
    # method implementation
    return {"message": "School updated"}


@app.delete("/schools/{school_id}")
def delete(school_id: int):
    # method implementation
    return {"message": "School deleted"}

````

### 5. Conclusion

FastAPI is very easy to get running and it comes with a lot of useful things by default, like built-in documentation. It has issues like any other framework, but it is being updated and improved, so it seems like a good choice if you need to write an API in Python.




