Lädt...

🔧 Building a Production-Ready To-Do API with FastAPI


Nachrichtenbereich: 🔧 Programmierung
🔗 Quelle: dev.to

Hey fellow Python devs! 👋

In this guide, we’ll build a To-Do API using FastAPI with production-ready features. If you're looking to sharpen your backend development skills or add a solid project to your portfolio, this tutorial is for you!

You'll learn how to:

✅ Set up a PostgreSQL database

✅ Define models with SQLAlchemy

✅ Validate data using Pydantic

✅ Implement CRUD operations with FastAPI

Let’s get started! 🚀

Project Setup

Step 1: Install Dependencies

Before we start coding, install the required dependencies:

pip install fastapi psycopg2 pydantic SQLAlchemy uvicorn python-dotenv

Step 2: Project Structure

Your project should be structured like this:

📂 todo_api_project
 ┣ 📜 main.py        # Entry point of the application
 ┣ 📜 database.py    # Database configuration
 ┣ 📜 model.py       # Database models
 ┣ 📜 schema.py      # Pydantic schemas
 ┣ 📜 route.py       # API routes
 ┗ 📜 requirements.txt # Dependencies

Step 3: Setting Up the Database

We’ll use PostgreSQL as our database. Create a file called database.py and add the following code:

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

DATABASE_URL = "postgresql://yourusername:yourpassword@localhost/todo_db"

engine = create_engine(DATABASE_URL)

sessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

BASE = declarative_base()

def get_db():
    db = sessionLocal()
    try:
        yield db
    finally:
        db.close()

Explanation

  • We use create_engine to connect to the PostgreSQL database.
  • sessionLocal manages database sessions.
  • BASE = declarative_base() allows us to define database models.
  • The get_db function provides a database session when needed.

Step 4: Creating the To-Do Model

In model.py, define the structure of your To-Do items using SQLAlchemy:

from sqlalchemy import Column, Integer, String, Boolean, TIMESTAMP, text
from database import BASE

class Todo(BASE):
    __tablename__ = "todos"

    id = Column(Integer, primary_key=True, index=True)
    title = Column(String, nullable=False)
    description = Column(String, nullable=True)
    published = Column(Boolean, server_default=text("False"))
    created_at = Column(TIMESTAMP(timezone=True), server_default=text("now()"))

Explanation

  • id: Auto-generated primary key.
  • title: Required (nullable=False).
  • description: Optional field (nullable=True).
  • published: Boolean field with a default value of False.
  • created_at: Stores the creation timestamp.

Step 5: Creating Pydantic Schemas

In schema.py, define how Pydantic will validate incoming request data:

from typing import Optional
from pydantic import BaseModel

class Todo(BaseModel):
    title: str
    description: Optional[str] = None
    published: bool = False

    class Config:
        orm_mode = True

class UpdateTodo(BaseModel):
    title: Optional[str] = None
    description: Optional[str] = None
    published: Optional[bool] = None

Explanation

  • Todo: Used for creating new tasks.
  • UpdateTodo: Used for updating tasks.
  • orm_mode = True: Ensures compatibility with SQLAlchemy models.

Step 6: Creating API Routes

Now, let’s create the API endpoints in route.py:

from fastapi import APIRouter, Depends, Query
from sqlalchemy.orm import Session
from database import get_db, engine
from schema import Todo, UpdateTodo
import model
from typing import List

# Create tables
model.BASE.metadata.create_all(bind=engine)

route = APIRouter()

1️⃣ Get All To-Dos

@route.get("/getalltodos")
def get_all_todo(db: Session = Depends(get_db)):
    todos = db.query(model.Todo).all()
    return todos if todos else []

✅ Fetches all tasks from the database.

2️⃣ Create a New To-Do

@route.post("/todo/create")
def create_todo(todo: Todo, db: Session = Depends(get_db)):
    todo_item = model.Todo(**todo.model_dump())
    db.add(todo_item)
    db.commit()
    db.refresh(todo_item)
    return todo_item

✅ Takes JSON input and adds a new task to the database.

3️⃣ Update a To-Do

@route.put("/todo/update/{post_id}", response_model=UpdateTodo)
def update_todo(new_post: UpdateTodo, post_id: int, db: Session = Depends(get_db)):
    todo = db.query(model.Todo).filter(model.Todo.id == post_id).first()
    if not todo:
        return {"error": "To-do not found"}

    update_data = new_post.model_dump(exclude_unset=True)

    for key, value in update_data.items():
        setattr(todo, key, value)

    db.commit()
    db.refresh(todo)
    return todo

✅ Updates an existing task based on post_id.

4️⃣ Get Published To-Dos

@route.get("/published_todo")
def get_published_todos(db: Session = Depends(get_db)):
    return db.query(model.Todo).filter(model.Todo.published == True).all()

✅ Fetches only published to-do items.

5️⃣ Get Draft To-Dos

@route.get("/draft_todo")
def get_draft_post(db: Session = Depends(get_db)):
    return db.query(model.Todo).filter(model.Todo.published == False).all()

✅ Fetches only unpublished (draft) tasks.

6️⃣ Get a To-Do by ID

@route.get("/getbyid/{todo_id}")
def get_by_id(todo_id: int, db: Session = Depends(get_db)):
    return db.query(model.Todo).filter(model.Todo.id == todo_id).first()

✅ Fetches a specific task by its id.

7️⃣ Search To-Dos

@route.get("/search", response_model=List[Todo])
def search_todo(name: str = Query(None), db: Session = Depends(get_db)):
    query = db.query(model.Todo)

    if name:
        query = query.filter(model.Todo.title.like(f"%{name}%") | model.Todo.description.like(f"%{name}%"))
        todos = query.all()
        return todos if todos else {"error": "No post found"}

    return []

✅ Searches tasks by title or description.

8️⃣ Delete a To-Do

@route.delete("/delete/{todo_id}")
def delete_post(todo_id: int, db: Session = Depends(get_db)):
    todo = db.query(model.Todo).filter(model.Todo.id == todo_id).first()
    db.delete(todo)
    db.commit()

✅ Deletes a task from the database.

Step 7: Running the API

Create main.py to start the server:

from fastapi import FastAPI
from route import route  

app = FastAPI()

@app.get("/")
def root():
    return {"hello": "world!!!"}

app.include_router(route)

Run the server:

uvicorn main:app --reload

Visit http://127.0.0.1:8000/docs to test the API! 🎉

Conclusion

You've built a To-Do API with FastAPI, PostgreSQL, and SQLAlchemy! This is a great project to showcase in your portfolio. Keep exploring and refining your skills! 🚀

Full code on my GitHub here

What do you think? Does this structure work for your blog? 😊

...

🔧 The FastAPI Deployment Cookbook: Recipe for deploying FastAPI app with Docker and DigitalOcean"


📈 27.51 Punkte
🔧 Programmierung

🔧 The FastAPI Deployment Cookbook: Recipe for deploying FastAPI app with Docker and DigitalOcean"


📈 27.51 Punkte
🔧 Programmierung

🔧 Understanding FastAPI: How FastAPI works


📈 27.51 Punkte
🔧 Programmierung

🔧 Supercharge Your FastAPI Security with fastapi-guard!


📈 27.51 Punkte
🔧 Programmierung

🔧 Understanding FastAPI Fundamentals: A Guide to FastAPI, Uvicorn, Starlette, Swagger UI, and Pydantic


📈 27.51 Punkte
🔧 Programmierung

🔧 FastAPI Beyond CRUD Full Course - A FastAPI Course


📈 27.51 Punkte
🔧 Programmierung

🔧 Deploying FastAPI, PostgreSQL, Celery & Redis on Render - FastAPI Beyond CRUD (Part 23)


📈 27.51 Punkte
🔧 Programmierung

🔧 Background Tasks with FastAPI Background Tasks and Celery + Redis - FastAPI Beyond CRUD (Part 20)


📈 27.51 Punkte
🔧 Programmierung

🔧 From FastAPI to Render: Building a Number Classification API with Docker.


📈 23.72 Punkte
🔧 Programmierung

🔧 From Code to Cloud: Building and Deploying a Smart Number Classification API with FastAPI


📈 23.72 Punkte
🔧 Programmierung

🔧 Serverless FastAPI Development: Building Player FC API on AWS


📈 23.72 Punkte
🔧 Programmierung

🔧 Building a Task Management API with Apache Cassandra and FastAPI


📈 23.72 Punkte
🔧 Programmierung

🔧 # 🚀 Building a User Management API with FastAPI and SQLite


📈 23.72 Punkte
🔧 Programmierung

🔧 Part 2: Building a Todo API with FastAPI: Step-by-Step Guide


📈 23.72 Punkte
🔧 Programmierung

🔧 Building a CRUD API with FastAPI and MongoDB


📈 23.72 Punkte
🔧 Programmierung

🔧 Building a REST API with FastAPI, Async SQLModel, and PostgreSQL


📈 23.72 Punkte
🔧 Programmierung

🔧 Building A Simple API For Your ML Model With FastAPI


📈 23.72 Punkte
🔧 Programmierung

🔧 Building an API using FastAPI and Uvicorn


📈 23.72 Punkte
🔧 Programmierung

🔧 Building a Retrieval-Augmented Generation (RAG) API and Frontend with FastAPI and React Native


📈 23.72 Punkte
🔧 Programmierung

🔧 Building a serverless GenAI API with FastAPI, AWS, and CircleCI


📈 23.72 Punkte
🔧 Programmierung

🔧 Building a FastAPI Book API with CI/CD Pipelines (Using Github Actions) and Docker Deployment


📈 23.72 Punkte
🔧 Programmierung

🔧 Building a Number Analysis API, Fun Facts and Math Insights with AWS Lambda and FastAPI


📈 23.72 Punkte
🔧 Programmierung

🔧 Fastapi from localhost to production (part 1)


📈 22.89 Punkte
🔧 Programmierung

🔧 FastAPI: The Ultimate Guide to Building High-Performance APIs with Python


📈 19.03 Punkte
🔧 Programmierung

🔧 Building a Simple Blog App Using FastAPI, HTML, CSS, and JSON


📈 19.03 Punkte
🔧 Programmierung

🔧 Guide: Building and Deploying a FastAPI App for Number Classification


📈 19.03 Punkte
🔧 Programmierung

🔧 Building a Real-Time Credit Card Fraud Detection System with FastAPI and Machine Learning


📈 19.03 Punkte
🔧 Programmierung

🔧 Building flask-jeroboam: bringing a taste of FastAPI to Flask


📈 19.03 Punkte
🔧 Programmierung

🔧 Building a Modern Web App: FastAPI + React TypeScript Template


📈 19.03 Punkte
🔧 Programmierung

🔧 Building JWT Auth Chaining with FastAPI and Python


📈 19.03 Punkte
🔧 Programmierung

🔧 Building an AI-Powered Chat Interface Using FastAPI and Gemini


📈 19.03 Punkte
🔧 Programmierung

🔧 Building a Contact Form Backend with FastAPI and Discord Integration


📈 19.03 Punkte
🔧 Programmierung

matomo