Skip to content

Auto-discovery

bluefox-core automatically discovers your models and routers by convention — no manual registration needed.

How it works

When the app starts, bluefox-core scans your project for files matching these patterns:

Pattern What it does
*/models.py Imports the module, registering models in BluefoxBase.metadata
*/api.py Imports the module, mounts the router attribute on the app

The scan covers:

  • Root level: models.py, api.py
  • App package: app/models.py, app/api.py
  • Any top-level package: items/models.py, users/api.py, etc.

Router discovery

Create a directory with an api.py file that exports a router:

# items/api.py
from fastapi import APIRouter

router = APIRouter()

@router.get("/")
async def list_items():
    return {"items": []}

@router.post("/")
async def create_item(name: str):
    return {"name": name}

The directory name becomes the URL prefix automatically:

File Mounted at
items/api.py /items
users/api.py /users
api.py / (root)
app/api.py / (root)

Multiple modules work together — each gets its own prefix:

myproject/
  items/
    api.py      → /items
    models.py   → auto-imported
  users/
    api.py      → /users
    models.py   → auto-imported
  main.py

Requirements

  • The file must be named api.py
  • It must export a variable named router that is a FastAPI APIRouter instance
  • Files without a router attribute are silently skipped

Model discovery

Models follow the same convention. Any models.py file with classes inheriting from BluefoxBase is imported automatically:

# users/models.py
from sqlalchemy.orm import Mapped, mapped_column
from bluefox_core import BluefoxBase

class User(BluefoxBase):
    __tablename__ = "users"

    id: Mapped[int] = mapped_column(primary_key=True)
    email: Mapped[str] = mapped_column(unique=True)
    name: Mapped[str]

This is used by both:

  • The app factory — models are available at startup
  • Alembic migrationsconfigure_alembic() uses the same discovery to find models for autogenerate

Inheritance check

If a model inherits from SQLAlchemy's DeclarativeBase directly instead of BluefoxBase, you'll see a warning:

WARNING Model users.models.User inherits from DeclarativeBase but not BluefoxBase.
It won't be tracked by Bluefox migrations.
Change it to inherit from BluefoxBase instead.

Explicit override

If your models don't follow the convention, set MODELS_MODULE:

MODELS_MODULE=myapp.db.all_models

When set, only this module is imported — convention scanning is skipped.