What is FastAPI: A Powerful and Enjoyable Python Web Framework

FastAPI is a new and powerful Python web framework that offers developers a fast and enjoyable experience for building web applications. With its impressive speed and comprehensive features, FastAPI is quickly gaining popularity among developers. In this article, we will explore the key features and benefits of FastAPI, and how it can enhance your web development process.

Why Choose FastAPI?

1. Unmatched Speed

One of the standout features of FastAPI is its exceptional speed. In fact, FastAPI is considered one of the fastest Python web frameworks available, rivaling the performance of popular frameworks like Node.js and Go. This speed is achieved through the use of asynchronous programming and advanced optimizations, allowing you to build high-performance applications that can handle heavy workloads with ease.

2. Detailed Documentation and Easy-to-Use Interface

FastAPI prides itself on its detailed and user-friendly documentation. The documentation provides comprehensive guides, tutorials, and examples, making it easy for developers to get started and quickly grasp the framework’s concepts. Additionally, FastAPI leverages the power of type hints, allowing you to validate and convert data seamlessly, resulting in cleaner and more robust code.

3. Type Hinting for Data Validation and Conversion

FastAPI leverages Python’s type hinting capabilities to provide automatic data validation and conversion. By using Pydantic models, you can define the shape of your incoming and outgoing data, ensuring that it adheres to the specified schema. This eliminates the need for manual data validation and conversion, resulting in more reliable and maintainable code.

4. Dependency Injection Made Easy

FastAPI makes it effortless to create plugins and manage dependencies through its built-in support for dependency injection. By using dependency injection, you can easily modularize your code, improve testability, and enhance code reusability. FastAPI’s dependency injection system allows you to inject dependencies into your routes, making it simple to access resources such as databases, external APIs, or authentication services.

Building a TODO App with FastAPI

To demonstrate the power and simplicity of FastAPI, let’s build a TODO app using the framework. The app will allow users to sign up, log in, add new TODO items, get a list of all TODOs, and delete or update existing TODO items. We will utilize the SQLAlchemy library for our data models and Pydantic models for data validation.

SQLAlchemy for Data Models

Our TODO app will have two main models: User and TODO. These models define the structure of our database tables and the relationships between them. With the help of SQLAlchemy, a popular database toolkit for Python, we can express our models easily and efficiently.

class User(Base):
    __tablename__ = "users"
    id = Column(Integer, primary_key=True, index=True)
    lname = Column(String)
    fname = Column(String)
    email = Column(String, unique=True, index=True)
    todos = relationship("TODO", back_populates="owner", cascade="all, delete-orphan")

class TODO(Base):
    __tablename__ = "todos"
    id = Column(Integer, primary_key=True, index=True)
    text = Column(String, index=True)
    completed = Column(Boolean, default=False)
    owner_id = Column(Integer, ForeignKey("users.id"))
    owner = relationship("User", back_populates="todos")

Once our data models are defined, we can proceed to configure SQLAlchemy to establish a connection with the database. This can be done by creating an engine and a sessionmaker.

import os
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

SQLALCHEMY_DATABASE_URL = os.environ['SQLALCHEMY_DATABASE_URL']
engine = create_engine(SQLALCHEMY_DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

Leveraging the Power of Type Hints

FastAPI allows us to leverage the power of type hints to define the shape of our incoming and outgoing data. We can use Pydantic models to specify the structure and constraints of our data, and FastAPI will automatically handle data validation and conversion for us.

In our TODO app, we will define several Pydantic models to represent different types of data. For example, we can define a UserCreate model to specify the data required for user signup, and a TODOCreate model for creating new TODO items.

from pydantic import BaseModel, EmailStr

class UserCreate(BaseModel):
    email: EmailStr

class TODOCreate(BaseModel):
    text: str
    completed: bool

These Pydantic models allow us to define the expected data shape and apply constraints such as minimum and maximum length, regex patterns, and more. FastAPI will handle the validation and conversion of data based on these models, ensuring the integrity of our data.

Request Handlers and Endpoints

FastAPI utilizes a decorator-based approach for defining request handlers and endpoints. We can define a request handler using the @app.post, @app.get, @app.put, or @app.delete decorators, depending on the HTTP method we want to handle.

For example, to handle the user signup process, we can define a request handler like this:

@app.post("/api/users", response_model=User)
def signup(user_data: UserCreate, db: Session = Depends(get_db)):
    # Add new user logic here

In this example, the @app.post decorator specifies that this request handler will handle HTTP POST requests to the “/api/users” endpoint. The response_model argument specifies the Pydantic model that will be used to validate and convert the response data.

We can also utilize dependency injection in our request handlers by using the Depends function. This allows us to inject dependencies such as database connections or authentication services into our request handlers.

Security Features

FastAPI provides built-in support for common security features, such as password hashing and JWT-based authentication. We can use libraries like Passlib for password hashing, and FastAPI’s OAuth2PasswordBearer for JWT-based authentication.

To hash passwords, we can define functions like verify_password and get_password_hash using Passlib:

from passlib.context import CryptContext

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

def verify_password(plain_password, hashed_password):
    return pwd_context.verify(plain_password, hashed_password)

def get_password_hash(password):
    return pwd_context.hash(password)

For JWT-based authentication, we can define functions like create_access_token and decode_access_token using the PyJWT library:

import jwt
from fastapi.security import OAuth2PasswordBearer

SECRET_KEY = os.environ['SECRET_KEY']
ALGORITHM = os.environ['ALGORITHM']

def create_access_token(*, data: dict, expires_delta: timedelta = None):
    # Token creation logic here

def decode_access_token(db, token):
    # Token decoding logic here

We can then define a login endpoint that generates JWTs upon successful login:

@app.post("/api/token", response_model=Token)
def login_for_access_token(db: Session = Depends(get_db), form_data: OAuth2PasswordRequestForm = Depends()):
    # Login endpoint logic here

CRUD Operations for TODOs

FastAPI makes it easy to implement CRUD (Create, Read, Update, Delete) operations for our TODO app. We can define request handlers for each operation, utilizing the appropriate Pydantic models and database functions.

For example, to retrieve a list of TODOs owned by the current user, we can define a request handler like this:

@app.get("/api/mytodos", response_model=List[TODO])
def get_own_todos(current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
    # Get user's TODOs logic here

Similarly, we can define request handlers for adding a new TODO, updating an existing TODO, and deleting a TODO item.

Testing with FastAPI

FastAPI provides a TestClient class that allows us to easily write tests for our API endpoints. We can use tools like pytest to run our tests and verify the correctness and functionality of our application.

For example, we can write a test to ensure that only authenticated users can create TODOs:

from starlette.testclient import TestClient
from .main import app

client = TestClient(app)

def test_unauthenticated_user_cant_create_todos():
    todo = dict(text="run a mile", completed=False)
    response = client.post("/api/todos", data=todo)
    assert response.status_code == 401

By writing tests for our application, we can ensure that our code is functioning correctly and handling different scenarios as expected.

Conclusion

FastAPI is a powerful and enjoyable Python web framework that brings speed, ease of use, and extensive documentation to the table. Its exceptional performance, detailed documentation, and built-in features like data validation, dependency injection, and authentication make it an excellent choice for building web applications.

By leveraging FastAPI’s capabilities, we can build high-performance applications with clean and maintainable code. The type hinting and Pydantic models enable efficient data validation and conversion, while the dependency injection system simplifies the management of dependencies.

If you’re looking to integrate AI and machine learning into your business and maximize its benefits, HSL is offering a free assessment to help you get started. Fill in the form below to take advantage of this opportunity.

[FORM HERE]

With FastAPI, you can unlock the full potential of Python and build web applications with speed, performance, and robustness. Whether you’re a beginner or an experienced developer, FastAPI provides a powerful framework to streamline your development process and deliver high-quality applications.

So, why wait? Start exploring FastAPI today and experience the joy of building web applications with ease and efficiency.

Are you interested in AI but don’t know where to start? Want to understand the role of an AI Architect? Check out our page and watch our informative video.

Learn More About Our AI Services