python

Are You Ready to Master CRUD Operations with FastAPI?

Whip Up Smooth CRUD Endpoints with FastAPI, SQLAlchemy, and Pydantic

Are You Ready to Master CRUD Operations with FastAPI?

Dive Into CRUD With FastAPI, SQLAlchemy, and Pydantic

Creating CRUD (Create, Read, Update, Delete) endpoints is like the bread and butter of building web apps. If you’re using FastAPI along with SQLAlchemy and Pydantic, you’re setting yourself up for a smooth ride. Let’s break down how to whip up a CRUD app with these tools, and don’t worry — we’ll keep things chill and easy to follow.

Getting Your Playground Ready

First things first, you need to make sure you’ve got all the necessary goodies installed. Use pip for that:

pip install fastapi uvicorn sqlalchemy psycopg2-binary

In this example, we’re rolling with SQLite because it’s straightforward, but if you vibe more with PostgreSQL or something else, switch it up however you like.

Building the Database Models

Alright, let’s start by creating our database models using SQLAlchemy. Think of these models as blueprints for your database tables.

from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession

Base = declarative_base()

class Item(Base):
    __tablename__ = "items"
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True)
    description = Column(String, index=True)

DATABASE_URL = "sqlite+aiosqlite:///./test.db"
engine = create_async_engine(DATABASE_URL, echo=True)
async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)

async def lifespan(app: FastAPI):
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)
    yield

Crafting Pydantic Models

Next up, we gotta define some Pydantic models. These schemas help in validating and serializing the data. They should mirror your database models but are used specifically for API interactions.

from pydantic import BaseModel

class ItemBase(BaseModel):
    name: str
    description: str

class ItemCreate(ItemBase):
    pass

class Item(ItemBase):
    id: int

    class Config:
        orm_mode = True

Setting Up FastAPI With Style

Now it’s time to roll up our sleeves and set up FastAPI and define those CRUD endpoints.

from fastapi import FastAPI, Depends
from fastapi.responses import JSONResponse
from fastapi.requests import Request
from fastapi.exceptions import HTTPException

app = FastAPI(lifespan=lifespan)

async def get_session() -> AsyncGenerator[AsyncSession, None]:
    async with async_session() as session:
        yield session

@app.post("/items/", response_model=Item)
async def create_item(item: ItemCreate, session: AsyncSession = Depends(get_session)):
    db_item = Item(name=item.name, description=item.description)
    session.add(db_item)
    await session.commit()
    await session.refresh(db_item)
    return db_item

@app.get("/items/", response_model=list[Item])
async def read_items(session: AsyncSession = Depends(get_session)):
    items = await session.execute(select(Item))
    return items.scalars().all()

@app.get("/items/{item_id}", response_model=Item)
async def read_item(item_id: int, session: AsyncSession = Depends(get_session)):
    item = await session.get(Item, item_id)
    if not item:
        raise HTTPException(status_code=404, detail="Item not found")
    return item

@app.put("/items/{item_id}", response_model=Item)
async def update_item(item_id: int, item: ItemCreate, session: AsyncSession = Depends(get_session)):
    db_item = await session.get(Item, item_id)
    if not db_item:
        raise HTTPException(status_code=404, detail="Item not found")
    db_item.name = item.name
    db_item.description = item.description
    await session.commit()
    await session.refresh(db_item)
    return db_item

@app.delete("/items/{item_id}")
async def delete_item(item_id: int, session: AsyncSession = Depends(get_session)):
    item = await session.get(Item, item_id)
    if not item:
        raise HTTPException(status_code=404, detail="Item not found")
    await session.delete(item)
    await session.commit()
    return JSONResponse(content={"message": "Item deleted"}, status_code=200)

Let’s Get This Show on the Road

To get everything up and running, just use this command:

uvicorn main:app --reload

Your FastAPI server will come alive, and you can start playing with your CRUD endpoints at http://localhost:8000.

Automated Swagger Documentation

One of the coolest things about FastAPI is the automated documentation it provides through Swagger UI. You can check it out at http://localhost:8000/docs and test your API endpoints right from your browser.

Taking It Up a Notch with FastCRUD

If you’re feeling adventurous and want even more streamlined CRUD operations, try using packages like FastCRUD. It brings features like automatic endpoint creation, dynamic query building, and pagination to the table, simplifying complex CRUD operations.

from fastcrud import FastCRUD, crud_router

item_router = crud_router(
    session=get_session,
    model=Item,
    create_schema=ItemCreate,
    update_schema=ItemUpdateSchema,
    path="/items",
    tags=["Items"],
)

app.include_router(item_router)

With this setup, you get CRUD endpoints for your Item model on autopilot, including support for joins, sorting, and pagination.

Wrapping Up

Building CRUD endpoints with FastAPI, SQLAlchemy, and Pydantic is super effective for managing data in your web apps. By following the steps above, you’ll have a robust and efficient API handling your basic operations — creating, reading, updating, and deleting data. Whether you stick with the basics or dive into advanced tools like FastCRUD, FastAPI’s got your back with a flexible and high-performance framework to meet all your needs. Happy coding!

Keywords: FastAPI, SQLAlchemy, Pydantic, CRUD endpoints, web apps, SQLite, PostgreSQL, automated documentation, FastCRUD, uvicorn



Similar Posts
Blog Image
How Can Serving Static Files in FastAPI Be This Effortless?

Unlocking the Ease of Serving Static Files with FastAPI

Blog Image
Can FastAPI Unlock the Secrets of Effortless Data Validation?

Unlock Effortless User Input Validation with FastAPI and Pydantic

Blog Image
Python’s Hidden Gem: Unlocking the Full Potential of the dataclasses Module

Python dataclasses simplify creating classes for data storage. They auto-generate methods, support inheritance, allow customization, and enhance code readability. Dataclasses streamline development, making data handling more efficient and expressive.

Blog Image
Mastering Python's Single Dispatch: Streamline Your Code and Boost Flexibility

Python's single dispatch function overloading enhances code flexibility. It allows creating generic functions with type-specific behaviors, improving readability and maintainability. This feature is particularly useful for handling diverse data types, creating extensible APIs, and building adaptable systems. It streamlines complex function designs and promotes cleaner, more organized code structures.

Blog Image
Are You Running Your FastAPI App Without a Dashboard? Here's How to Fix That!

Guard Your FastAPI: Transform Monitoring with Prometheus and Grafana for a Smooth, Stable App

Blog Image
Python Metaclasses: The Secret Weapon for Supercharging Your Code

Explore Python metaclasses: Customize class creation, enforce standards, and design powerful APIs. Learn to harness this advanced feature for flexible, efficient coding.