Skip to content

MiguelAngelBaquero/fastapi

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Movies FastAPI

Building a simple API with FastAPI and PostgreSQL for Movies.

FastAPI is a web framework for building APIs with Python. In this project I built an API with CRUD (Create, Read, Update, Delete) operations and high performance.

This project is appropriate for beginners or experienced developers.

Before you begin

Make sure you've previously installed Python on your OS, this API has Python 3.x compatibility.

If you want to deploy the application once you're done building it, the common approach is to build a Linux container image using Docker. Also, you can run PostgreSQL from a container, so installing Docker is highly recommended.

At last but not least, is a good idea to install both database and API clients, such as PgAdmin and ThunderClient.

Libraries

Setting up the project structure

Create a new directory called app/. In this path you can put all files realted to the API.

The main.py file is the starting point to import libraries, modules and different utilities. You can name your modules whatever you feel like and remember to create an __init.py__ file everytime you generate a new directory inside the app/ path.

.
├── app
│   ├── main.py
│   ├── ...
│   ├── schemas
│   │   ├── __init__.py
│   │   └── ...
│   └── models
│       ├── __init__.py
│       └── ...

Finally, you need to create two files at the project's root path level:

  • Dockerfile
  • requirements.txt

The final result should look like the following structure:

.
├── app
│   ├── main.py
│   └── ...
├── Dockerfile
└── requirements.txt

Database container

A docker-compose.yml file is provided in this project in case that you want to run the database from a Docker container.

╰─ docker-compose up

Building the database container with docker compose is completely optional. If you already have a local machine or a cloud service running PostgreSQL, then you can definitely reuse it. Just keep in mind that you require your database IP address.

Dev Environment

We are taking advantage of the features of Uvicorn, which is a a ASGI web server and it's helpful to test the app before any deployment.

To configure the dev environment, follow the next steps:

  1. Install virtual environment and web server dependencies:
pip install virtualenv
pip install uvicorn
  1. Generate a new virtual environment:
╰─ Unix/macOS:
python3 -m venv .venv

╰─ Windows
py -m venv .venv
  1. Activate the virtual environment
╰─ Unix/macOS:
source .venv/bin/activate

╰─ Windows
.venv\Scripts\activate
  1. Install dependencies
pip install -r requirements.txt
  1. Initiate Uvicorn
cd app
uvicorn main:app --reload

Deployment

Build the Docker image

Once you finish your API, you can build a Docker image to deploy your app.

Go to the project directory in where your Dockerfile is and type:

╰─ docker build -t myimage .

Start the Docker Container

Run a container based on your image:

╰─ docker run -d --name mycontainer -p 80:80 myimage

Docker containers

Check your application working

You should be able to check it in your Docker container's URL, for example:

App's home - container

Container's IP address

If you are running both your app and dabase containers on the same machine, then you need to get the real IP address from the database container. This is due to the default network mode on Docker, bridge.

Once you've gotten the IP addres, set it up in database.py.

If you are running tests on your local machine while using a web server like Uvicorn, switch the IP address back to localhost in database.py.

╰─ docker ps

CONTAINER ID   IMAGE      COMMAND                  CREATED       STATUS          PORTS                    NAMES
a80117d31c68   postgres   "docker-entrypoint.s…"   3 weeks ago   Up 16 seconds   0.0.0.0:5432->5432/tcp   postgres

╰─ docker inspect postgres

[
    {
        "Id": "a80117d31c680073c77cf5ca7ab56a034193e04eabb0c55805eff56b902d53ab",
        "Created": "2024-04-24T02:07:16.110059554Z",
        "Path": "docker-entrypoint.sh",
        "Args": [
            "postgres"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 362,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2024-05-16T06:33:40.41262039Z",
            "FinishedAt": "2024-05-15T03:23:33.567499664Z"
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "a9ecb0d79e3ce60d22deffee7c89c5b6f441583a69232c85fadd110c974d2c31",
            "SandboxKey": "/var/run/docker/netns/a9ecb0d79e3c",
            "Ports": {
                "5432/tcp": [
                    {
                        "HostIp": "0.0.0.0",
                        "HostPort": "5432"
                    }
                ]
            },
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "bd1b3c1e1758bd6ae0355f7222bff6c4414fa334ada30340752b19f59ceaf52c",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:02",
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "MacAddress": "02:42:ac:11:00:02",
                    "NetworkID": "e8c08dac119203343c53332eddecafc2f27c08cc4d99fecf0694f7cf1f923000",
                    "EndpointID": "bd1b3c1e1758bd6ae0355f7222bff6c4414fa334ada30340752b19f59ceaf52c",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "DriverOpts": null,
                    "DNSNames": null
                }
            }
        }
    }
]

Database Model

SqlAlchemy has a feature where you can add a single table model or a completely complex database model.

Check the models.py file to see more details about this project's database model.

Db Model

API Consumption

The API is designed to perform CRUD operations, so here is a list of the available HTTP methods:

  • GET
  • POST
  • DELETE
  • PATCH

API routes

  • GET /movies Read all movies
    • Optional parameters: skip (int default 0), limit (int default 100)
  • POST /movies Create a movie
  • GET /movies{movie_id} Read movie by ID
  • DELETE /movies{movie_id} Delete movie by ID
  • PATCH /movies{movie_id} Update movie by ID (partial updates accepted)

Some examples

  • Create movies.

Create movie

Create movie

  • Get a movie to be updated.

Movie to update

  • Update a movie.

Movie updated

  • Get a movie to be deleted.

Movie to delete

  • Delete a movie.

Movie deleted

  • Get all movies.

Get all movies

About

Simple API using FastAPI, Python and PostgreSQL

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published