FastAPI: Building a Complete Application

By khoanc, at: April 13, 2023, 10:33 p.m.

Estimated Reading Time: 12 min read

FastAPI: Building a Complete Application
FastAPI: Building a Complete Application

FastAPI: Building a Complete Application

FastAPI, that is a modern and high-performance web framework for building APIs with Python, combines the simplicity of Flask with the performance of Node.js frameworks like Express. In this article, we will explore the step-by-step process of building a complete application using FastAPI, focusing on a book store management system as an example.

Check our public repo to get more details
 

Introduction to FastAPI

FastAPI is known as a highly efficient and easy to use framework. Those two important features (type hints and asynchronous programming) provide a seamless development experience. Its main features are:

  • request validation
  • dependency injection
  • support for websockets
     

Setting up a FastAPI Project

In this article, we are going to build a bookstore management application using FastAPI.

First, we create a virtual environment to isolate our dependencies. 

mkdir bookstore  # create a directory
cd bookstore  # go to the bookstore directory
python -m venv venv  # create a virtualenv
source venv/bin/activate  # activate the virtualenv
pip install fastapi uvicorn  # Install required packages


Check our public repo to get more details


Defining Models and Database Schema

Lets define the models and database schema. We can use an Object-Relational Mapping (ORM) tool like SQLAlchemy to interact with the database.

Here's an example of how we can define a Book model:

from sqlalchemy import Column, Integer, String, Float
from database import Base


class Book(Base):
    __tablename__ = 'books'
    id = Column(Integer, primary_key=True)
    title = Column(String, nullable=False)
    author = Column(String, nullable=False)
    price = Column(Float, nullable=False)


Check our public repo to get more details


Creating Routes and Endpoints

Once we have our models defined, we can start creating routes and endpoints for our API. FastAPI uses decorators to define routes, and type hints to specify the expected request and response types.

Here's an example of how we can define a route to retrieve a list of books:

from fastapi import FastAPI
from typing import List
from models import Book

app = FastAPI()

@app.get("/books", response_model=List[Book])
async def get_books():
    # Retrieve books from the database
    books = db.query(Book).all()
    return books


Check our public repo to get more details


Implementing CRUD Operations

We, then, need to implement CRUD (Create, Read, Update, Delete) operations for managing books. We can create routes for each operation and handle the corresponding requests.

Here's an example of how we can implement the create operation:

@app.post("/books", response_model=Book)
async def create_book(book: BookCreate):
    # Create a new book
    new_book = Book(title=book.title, author=book.author, price=book.price)
    db.add(new_book)
    db.commit()
    db.refresh(new_book)
    return new_book


Check our public repo to get more details


Handling Authentication and Authorization

For a secure application, authentication and authorization should be added to this project. FastAPI provides built-in support (security) for integrating with popular authentication mechanisms like OAuth2 and JWT (JSON Web Tokens).

Here's an example of how we can add authentication to a route:

from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from .models import User

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

@app.get("/books", response_model=List[Book])
async def get_books(token: str = Depends(oauth2_scheme)):
    # Verify the token and retrieve the books
    user = await authenticate_user(token)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid authentication credentials",
            headers={"WWW-Authenticate": "Bearer"},
        )
    books = db.query(Book).all()
    return books


Check our public repo to get more details


Validating Request Data

FastAPI has powerful request data validation capabilities. We can use Pydantic models to define the expected request payloads and automatically validate the incoming data. Meaningful error messages are returned in the FastAPI's response.

Here's an example of how we can validate the request data for creating a book:

from pydantic import BaseModel

class BookCreate(BaseModel):
    title: str
    author: str
    price: float


Uploading and Serving Files

In some applications, we may need to handle file uploads and serve the files to clients. That can be easily done by UploadFile type from the fastapi module. We can define a route that accepts file uploads and saves them to the server.

Here's an example of how we can handle file uploads:

from fastapi import UploadFile, File

@app.post("/upload")
async def upload_file(file: UploadFile = File(...)):
    contents = await file.read()
    # Save the file or process its contents
    # ...
    return {"filename": file.filename}


Adding Pagination to API Responses

FastAPI provides utilities for adding pagination to API endpoints using page number and limit. 

Here's an example of how we can implement pagination:

@app.get("/books")
async def get_books(page: int = 1, limit: int = 10):
    offset = (page - 1) * limit
    books = db.query(Book).offset(offset).limit(limit).all()
    return books


Implementing Real-time Communication with WebSockets

FastAPI also supports real-time communication through WebSockets. We can create WebSocket routes and handle incoming WebSocket connections. This allows us to build interactive and event-driven applications.

Here's an example of how we can implement a WebSocket route:

from fastapi import WebSocket

@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    while True:
        data = await websocket.receive_text()
        await websocket.send_text(f"You said: {data}")


Writing Tests for FastAPI Applications

Testing is an essential part of any software development process. FastAPI provides tools for writing tests to ensure the correctness and reliability of our applications. We can use the TestClient class from the fastapi.testclient module to simulate HTTP requests and validate the responses.

Here's an example of how we can write tests for our FastAPI application:

from fastapi.testclient import TestClient
from .main import app

client = TestClient(app)

def test_get_books():
    response = client.get("/books")
    assert response.status_code == 200
    assert response.json() == []


Containerizing and Deploying FastAPI Applications

We can containerize it using tools like Docker and deploy it to a production environment. Containerization allows us to package our application and its dependencies into a portable and isolated environment. We can then deploy the container to cloud platforms like AWS or Google Cloud.

Here's an example of how we can create a Dockerfile for our FastAPI application:

dockerfile
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9

COPY ./app /app


Conclusion

In this article, we have explored the process of building a complete application with FastAPI. We started by setting up a project, defining models and database schema, and creating routes and endpoints. We implemented CRUD operations, handled authentication and authorization, validated request data, and added advanced features like file uploads, pagination, and WebSockets. We also discussed writing tests for FastAPI applications and containerizing and deploying them. FastAPI's simplicity and performance make it an excellent choice for building modern web applications.

Check our public repo to get more details

A sample FastAPI application


FAQs


Q1: What is FastAPI?

FastAPI is a modern and high-performance web framework for building APIs with Python. It combines the simplicity of Flask with the performance of Node.js frameworks like Express.


Q2: Is FastAPI suitable for large-scale applications?

Yes, FastAPI is suitable for large-scale applications. Its asynchronous nature and performance optimizations make it well-suited for handling high traffic and demanding workloads.


Q3: Can I use FastAPI with a different database?

Yes, FastAPI is compatible with various databases. It works seamlessly with SQL databases like PostgreSQL and MySQL, as well as NoSQL databases like MongoDB.


Q4: Does FastAPI support authentication out of the box?

Yes, FastAPI provides built-in support for integrating with popular authentication mechanisms like OAuth2 and JWT (JSON Web Tokens). It makes it easy to secure your API endpoints.


Q5: How can I deploy a FastAPI application to production?

FastAPI applications can be deployed to production using various methods. You can containerize your application using tools like Docker and deploy it to cloud platforms like AWS or Google Cloud. Alternatively, you can deploy it to a traditional web server using ASGI servers like Uvicorn or Gunicorn.


Q6: Can I build a website with FastAPI?

Yes, you can build a website with FastAPI. While FastAPI is primarily designed for building APIs, it can also be used to serve web pages. FastAPI supports the creation of HTML templates and can render dynamic content for building server-side rendered websites.


Q7: How do I organize my FastAPI project?

Organizing your FastAPI project depends on your preferences and the size of your project. However, a common approach is to follow a modular structure. You can organize your project into separate modules or packages, each responsible for a specific area or functionality. This helps maintain a clean codebase and allows for better scalability and reusability. There are few blog posts suggesting best practices to organize a FastAPI project, ex: https://github.com/zhanymkanov/fastapi-best-practices


Q8: Is FastAPI good for bigger projects?

Yes, FastAPI is well-suited for bigger projects. Its performance and asynchronous capabilities make it a powerful choice for handling complex and high-traffic applications. FastAPI's use of modern Python features, such as type hints and dependency injection, also promotes maintainability and scalability.


Q9: Can I use FastAPI for the backend?

Yes, FastAPI is primarily designed for building backend applications. It excels at creating high-performance web APIs and can handle various backend tasks, such as processing requests, interacting with databases, and implementing business logic. FastAPI is a great choice for developing the backend of your applications.


Q10: What is the fastest backend API language?

The speed of a backend API language depends on various factors, including the specific implementation, hardware, and workload. However, FastAPI, built with Python, is known for its impressive performance. It leverages asynchronous programming and modern Python features, making it one of the fastest backend API frameworks available.
 

Reference