Skip to content

A python backend with sqlalchemy, alembic, poetry, fastapi and linters

Notifications You must be signed in to change notification settings

vysakh0/python-backend

Repository files navigation

TODOs API

Setup

Prerequisites

  • Python 3.9+
  • Poetry
  • PostgreSQL
  1. Set up environment variables:
cp .env.example .env
# Edit .env with your database credentials
  1. Run migrations:
poetry run alembic upgrade head

Installation

  1. Install dependencies:
poetry install
# Install pre-commit hooks
poetry run pre-commit install
  1. Run the application:
poetry run dev

The API will be available at http://localhost:8000

Code Quality Tools

This project uses several tools to ensure code quality:

  • Ruff: For linting and formatting
  • MyPy: For static type checking

Pre-commit Checks

Before committing your changes, run the following command to ensure all code quality checks pass:

poetry run check

This will:

  • Check code formatting
  • Run type checks
  • Verify naming conventions
  • Ensure all linting rules are followed

Fix any issues reported before committing your changes.

Naming Conventions

Database & Models

  • Table names: plural, snake_case (e.g., todos, user_profiles)
  • Model files: singular, snake_case (e.g., todo.py, user_profile.py)
  • Model classes: singular, PascalCase (e.g., Todo, UserProfile)
  • Column names: snake_case (e.g., created_at, user_id)

API & Routes

  • API route files: plural, snake_case (e.g., todos.py, user_profiles.py)
  • Route paths: plural, kebab-case (e.g., /todos, /user-profiles)

REST API Function Naming

For REST endpoints, use simple verbs that match the HTTP method:

# Collection endpoints
@router.post("/")         def create()      # Create a new resource
@router.get("/")          def list_all()    # List all resources

# Single resource endpoints
@router.get("/{id}")      def get()         # Get a single resource
@router.put("/{id}")      def update()      # Update a resource
@router.delete("/{id}")   def delete()      # Delete a resource

# Nested resource endpoints
@router.post("/{id}/sub") def create_sub()  # Create a nested resource
@router.get("/{id}/sub")  def list_subs()   # List nested resources

Example URL patterns:

  • GET /todos - List all todos
  • POST /todos - Create a new todo
  • GET /todos/1 - Get todo with ID 1
  • PUT /todos/1 - Update todo with ID 1
  • DELETE /todos/1 - Delete todo with ID 1
  • POST /todos/1/comments - Create a comment on todo 1
  • GET /todos/1/comments - List comments for todo 1

Services & Schemas

  • Service files: singular, snake_case (matches model name)
  • Schema files: singular, snake_case (matches model name)
  • Schema classes: PascalCase with purpose suffix (e.g., TodoCreate, UserUpdate)

Service Layer Function Naming

For service layer functions, use descriptive names that include both verb and entity:

# CRUD operations in services
def create_todo()      # Create a new todo
def get_todos()        # Get all todos
def get_todo()         # Get single todo
def update_todo()      # Update a todo
def delete_todo()      # Delete a todo

Unlike API routes where the context is provided by HTTP method and URL path, service functions should be self-descriptive as they might be called from different contexts (API routes, background jobs, CLI commands, etc.).

Reference implementations:

  • API Routes: See api/todos.py for REST endpoint conventions
  • Services: See services/todo.py for service layer conventions

VSCode Extensions

For the best development experience, install these VSCode extensions:

  1. Python
  2. Ruff
  3. Mypy

Project Structure

your-repo-name/
├── api/
│   └── todos.py
├── models/
│   ├── __init__.py
│   └── todo.py
├── schemas/
│   ├── database.py
│   └── todo.py
├── services/
│   └── todo.py
├── app.py
├── pyproject.toml
└── .pre-commit-config.yaml

Development Workflow

Adding a New Feature (e.g., a new model)

Using the todos implementation as reference, follow these steps:

  1. Create the database migration

    # Create a new migration file
    poetry run alembic revision -m "create_your_table_name"
    
    # Edit the generated file in migrations/versions/
    # See migrations/versions/*_create_todos_table.py for reference
  2. Create the model

    • Add models/your_model.py (singular)
    • See models/todo.py for reference
    • Import it in models/__init__.py with # noqa: F401:
      from models.your_model import YourModel  # noqa: F401
      The noqa: F401 comment tells linters to ignore the "unused import" warning, as these imports are needed for SQLAlchemy/Alembic model registration.
  3. Create the schemas

    • Add schemas/your_model.py (singular)
    • Define base model and CRUD variants (Create, Update)
    • See schemas/todo.py for reference
  4. Create the service layer

    • Add services/your_model.py (singular)
    • Implement CRUD operations
    • See services/todo.py for reference
  5. Create the API routes

    • Add api/your_models.py (plural)
    • Implement REST endpoints
    • See api/todos.py for reference
  6. Register the router

    • Update app.py to include your new router
    from api.your_models import router as your_models_router
    app.include_router(your_models_router, prefix="/your-models", tags=["your-models"])
  7. Run the migration

    poetry run alembic upgrade head
  8. Test your endpoints

    # Example CRUD operations
    curl -X POST "http://localhost:8000/your-models/" -d '{"field": "value"}'
    curl "http://localhost:8000/your-models/"

Always follow the naming conventions and use the existing implementations as reference. Each layer (models, schemas, services, api) has its own conventions as documented above.

About

A python backend with sqlalchemy, alembic, poetry, fastapi and linters

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published