Migrating a Super Simple CRUD App from Flask to FastAPI
Tags: fastapi, flask, python, webdev
Published: 2021-07-30 20:51:57

## What is FastAPI and Why Do I Need It?

Flask has been one of the more popular Python frameworks for many years, but it’s time for an update. Today, we’ll be discussing Flask’s faster, more efficient cousin: FastAPI. Compared to Flask, FastAPI is more performant and has Swagger documentation and other goodies built-in. If you want to run a Python web application in production in 2021, you’ll want to use FastAPI. 

While there are some syntactical differences between how you write Flask and how you write FastAPI, you’ll find that they’re quite similar. Today we’re going to migrate a simple CRUD app from using Flask to Fast. So follow along!

Here is the original Flask code:
```
from flask import Flask, request

app = Flask(__name__)

@app.route('/basic_api/entities/<int:entity_id>', methods=['GET', 'PUT', 'DELETE'])
def entity(entity_id):
    if request.method == "GET":
        return {
            'id': entity_id,
            'message': 'This endpoint should return the entity {} details'.format(entity_id),
            'method': request.method
        }
    if request.method == "PUT":
        return {
            'id': entity_id,
            'message': 'This endpoint should update the entity {}'.format(entity_id),
            'method': request.method,
            'body': request.json
        }
    if request.method == "DELETE":
        return {
            'id': entity_id,
            'message': 'This endpoint should delete the entity {}'.format(entity_id),
            'method': request.method
        }
```

Now we’re going to break down each piece of this Flask code, and show you the equivalent code in FastAPI. First up, importing the libraries and instantiating the application object:

```
from flask import Flask, request
 
app = Flask(__name__)


from typing import Optional
from fastapi import FastAPI
 
app = FastAPI()

```

Next up, let’s rewrite the `/basic_api/entities/<int:entity_id>` endpoint in FastAPI.

```
@app.route('/basic_api/entities/<int:entity_id>', methods=['GET', 'PUT', 'DELETE'])
def entity(entity_id):
   if request.method == "GET":
       return {
           'id': entity_id,
           'message': 'This endpoint should return the entity {} details'.format(entity_id),
           'method': request.method
       }
   if request.method == "PUT":
       return {
           'id': entity_id,
           'message': 'This endpoint should update the entity {}'.format(entity_id),
           'method': request.method,
           'body': request.json
       }
   if request.method == "DELETE":
       return {
           'id': entity_id,
           'message': 'This endpoint should delete the entity {}'.format(entity_id),
           'method': request.method
       }
 
```

Note that in FastAPI, the request methods are defined as methods on the FastAPI object, for instance `@app.get, @app.put, @app.post`, etc rather than as a parameter. Also note that instead of stating the type of the url parameter `entity_id`, within the route, it’s instead typed as a parameter in `entity()`

```
@app.get('/basic_api/entities/{entity_id}')
def entity(entity_id: int):
   return {
       'id': entity_id,
       'message': 'This endpoint should return the entity {} details'.format(entity_id),
   }
 
 
@app.put('/basic_api/entities/{entity_id}')
def entity(entity_id: int, body: Entity):
   return {
       'id': entity_id,
       'message': 'This endpoint should update the entity {}'.format(entity_id),
       'body name': body.name
   }
 
 
@app.delete('/basic_api/entities/{entity_id}')
def entity(entity_id: int):
   return {
       'id': entity_id,
       'message': 'This endpoint should delete the entity {}'.format(entity_id),
   }

```

Also note that in the put request route, we are passing along, as `body`, an `Entity` object. To define this object, we create a new class that inherits from `BaseModel`. 

All together, the FastAPI application looks like:

```
from pydantic import BaseModel
 
 
class Entity(BaseModel):
   name: str
   description: Optional[str] = None
 

from pydantic import BaseModel
from typing import Optional
from fastapi import FastAPI
 
app = FastAPI()
 
 
class Entity(BaseModel):
   name: str
   description: Optional[str] = None
 
@app.get('/basic_api/entities/{entity_id}')
def entity(entity_id: int):
   return {
       'id': entity_id,
       'message': 'This endpoint should return the entity {} details'.format(entity_id),
   }
 
 
@app.put('/basic_api/entities/{entity_id}')
def entity(entity_id: int, body: Entity):
   return {
       'id': entity_id,
       'message': 'This endpoint should update the entity {}'.format(entity_id),
       'body name': body.name
   }
 
 
@app.delete('/basic_api/entities/{entity_id}')
def entity(entity_id: int):
   return {
       'id': entity_id,
       'message': 'This endpoint should delete the entity {}'.format(entity_id),
   }
 
```

And that’s it! You can save the `main.py` file and run the server with

```
uvicorn main:app --reload
```



This will bring the server up on `http://localhost:8000`

One of the nice features of FastAPI is that it comes with Swagger already integrated. You can access it at `http://localhost:8000/docs`

From there, you can test each of your endpoints to see that they work!

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xji57bhff4ku3f9kx5hs.PNG)