DEV Community

Sanoy24
Sanoy24

Posted on

Building a Robust E-Commerce API with FastAPI: A Deep Dive

In the world of modern web development, FastAPI has emerged as a superstar framework for building high-performance APIs with Python. Its speed, ease of use, and automatic documentation make it an ideal choice for complex applications like e-commerce platforms.

In this post, I'll take you through the journey of building a comprehensive E-Commerce RESTful API using FastAPI. We'll explore the architecture, key features, and dive into some code to see how it all comes together.

Why FastAPI for E-Commerce?

E-commerce systems require reliability, speed, and scalability. FastAPI checks all these boxes:

  • High Performance: On par with NodeJS and Go (thanks to Starlette and Pydantic).
  • Type Safety: Built on Python 3.10+ type hints, reducing bugs and improving editor support.
  • Auto-Documentation: Generates interactive Swagger UI and ReDoc automatically.
  • Async Support: Native support for asynchronous programming, perfect for I/O-bound tasks like database queries.

Project Overview

Our project is a fully functional backend for an online store. It's designed to be modular, scalable, and secure.

Key Features

  • User Management: Secure registration and login with JWT (JSON Web Tokens) and Argon2 hashing.
  • Product Catalog: Hierarchical category structure and detailed product management.
  • Shopping Cart: Persistent cart functionality for users.
  • Order Processing: Complete lifecycle management from order creation to history.
  • Reviews & Ratings: Allow users to leave feedback on products.
  • Address Management: Handling shipping and billing addresses.

The Tech Stack

  • Framework: FastAPI
  • Database: SQLAlchemy (ORM) + Alembic (Migrations)
  • Validation: Pydantic
  • Authentication: PyJWT + Argon2-cffi
  • Logging: Loguru
  • Deployment: Docker support included

Architecture & Structure

I've adopted a clean, modular structure to keep the codebase maintainable:

app/
├── api/          # Route handlers (v1/)
├── core/         # Config and security
├── crud/         # Database operations
├── db/           # Session management
├── models/       # SQLAlchemy models
├── schema/       # Pydantic schemas
├── services/     # Business logic
└── main.py       # Entry point
Enter fullscreen mode Exit fullscreen mode

This separation of concerns ensures that our business logic is decoupled from the API layer, and database models are distinct from the API schemas.

Code Deep Dive

Let's look at some interesting parts of the implementation.

1. The Product Model (app/models/product.py)

We use SQLAlchemy 2.0 style with Mapped and mapped_column for a modern, type-hinted definition.

class Product(Base):
    __tablename__ = "products"

    id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
    name: Mapped[str] = mapped_column(String(255), nullable=False)
    slug: Mapped[str] = mapped_column(String(255), unique=True, nullable=False)
    price: Mapped[float] = mapped_column(Numeric(10, 2), nullable=False)
    stock_quantity: Mapped[int] = mapped_column(default=0)

    # Relationships
    category: Mapped["Category"] = relationship("Category", back_populates="products")
    reviews: Mapped[List["Review"]] = relationship(
        "Review", back_populates="product", cascade="all, delete-orphan"
    )
Enter fullscreen mode Exit fullscreen mode

2. Clean Routing (app/api/v1/init_routes.py)

Instead of cluttering main.py, we centralize our route registration. This makes it easy to add new modules or version our API.

def init_routes(app: FastAPI):
    app.include_router(router=healthcheck.router, prefix="/healthcheck")
    app.include_router(router=user.router, prefix="/users")
    app.include_router(router=category.router, prefix="/category")
    app.include_router(router=product.router, prefix="/product")
    app.include_router(router=cart.router, prefix="/cart")
    app.include_router(router=order.router, prefix="/order")
Enter fullscreen mode Exit fullscreen mode

3. Robust Application Setup (app/main.py)

Our main.py handles middleware, exception handlers, and metadata configuration.

app = FastAPI(
    title="E-Commerce Backend API",
    description="RESTful API for managing the product catalog...",
    version="1.0.0",
    docs_url="/docs",
    redoc_url="/redoc",
)

app.add_middleware(LoggingMiddleware)

@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
    # Custom error formatting
    return JSONResponse(
        status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
        content={"error": "ValidationError", "fields": errors},
    )
Enter fullscreen mode Exit fullscreen mode

Best Practices Implemented

  • Dependency Injection: FastAPI's dependency injection system is used for database sessions and current user retrieval, making testing easier.
  • Middleware: Custom logging middleware ensures we have visibility into every request.
  • Global Exception Handling: We catch SQLAlchemyError and generic Exception to prevent leaking internal server details to the client.

What's Next?

This project serves as a solid foundation. Future enhancements could include:

  • Redis Caching: To speed up product catalog reads.
  • Celery Tasks: For sending emails and processing payments asynchronously.
  • Elasticsearch: For advanced product search capabilities.

Conclusion

Building an e-commerce API with FastAPI is a rewarding experience. The framework's design encourages best practices while giving you the speed you need.

Check out the full code on GitHub github repo link and feel free to contribute!

Happy Coding✌️!

Top comments (0)