Skip to content

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