How to Add Custom Dependencies to FastCRUD Endpoints: A Complete Guide

FastCRUD injects custom dependencies into auto-generated CRUD operations via the create_deps, read_deps, read_multi_deps, update_deps, delete_deps, and db_delete_deps parameters, automatically wrapping each callable in FastAPI's Depends during router construction.

FastCRUD is a Python library that auto-generates FastAPI CRUD endpoints from SQLAlchemy models. While the library handles database sessions automatically, production applications require additional layers such as authentication, authorization, or multi-tenant context. According to the benavlabs/fastcrud source code, the library exposes explicit dependency parameters for each operation type and processes them through an internal inject_dependencies utility that validates and wraps callables before passing them to FastAPI's router factory.

How Dependency Injection Works in FastCRUD

FastCRUD constructs its FastAPI routers by composing dependency injection blocks supplied at router creation time. The flow follows three distinct stages:

  1. User-provided callables are passed to crud_router through specific dependency parameters defined in fastcrud/endpoint/crud_router.py at lines 29-35
  2. The EndpointCreator class builds each route via self.router.add_api_route(), merging the dependencies by calling inject_dependencies(deps) as shown in fastcrud/endpoint/endpoint_creator.py at lines 71-78
  3. The inject_dependencies function in fastcrud/fastapi_dependencies.py (lines 174-188) validates that each object is callable and wraps it in fastapi.Depends

Because dependency objects are created once at router construction time, FastAPI resolves them automatically on every request without requiring boilerplate in your view functions.

Adding Dependencies to Standard CRUD Endpoints

FastCRUD provides six explicit parameters for injecting dependencies into specific operations:

  • create_deps – Applied to the POST/create endpoint
  • read_deps – Applied to the GET/read single endpoint
  • read_multi_deps – Applied to the GET/read multiple (list) endpoint
  • update_deps – Applied to the PUT/PATCH/update endpoint
  • delete_deps – Applied to the soft DELETE endpoint
  • db_delete_deps – Applied to the hard DELETE endpoint

Each parameter accepts a list of callables that FastCRUD automatically wraps with Depends.

Example: Requiring Authentication for All Operations


# deps.py

from fastapi import Depends, HTTPException, status

def get_current_user(token: str = Depends(...)):
    if token != "secret-token":
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
    return {"id": 1, "name": "alice"}

# router.py

from fastcrud.endpoint import crud_router
from .models import Item
from .schemas import ItemCreate, ItemUpdate, ItemRead
from .deps import get_current_user

router = crud_router(
    session=async_session,
    model=Item,
    create_schema=ItemCreate,
    update_schema=ItemUpdate,
    select_schema=ItemRead,
    create_deps=[get_current_user],
    read_deps=[get_current_user],
    read_multi_deps=[get_current_user],
    update_deps=[get_current_user],
    delete_deps=[get_current_user],
    db_delete_deps=[get_current_user],
)

In this configuration, every CRUD route receives Depends(get_current_user) automatically. The router is built once; FastAPI resolves the dependency on every request.

Adding Dependencies to Custom Routes

For endpoints that extend beyond standard CRUD operations, FastCRUD exposes the add_custom_route method in EndpointCreator. This method accepts a dependencies parameter that is processed by the same inject_dependencies utility used for standard operations.

According to fastcrud/endpoint/endpoint_creator.py at lines 71-79, custom routes support dependency injection through the following pattern:


# custom_deps.py

from fastapi import Depends, HTTPException

def verify_admin(user: dict = Depends(get_current_user)):
    if not user.get("is_admin"):
        raise HTTPException(status_code=403, detail="Admin only")
    return True

# router.py

from fastcrud.endpoint import crud_router
from .custom_deps import verify_admin

# First, create the standard router

router = crud_router(...)

# Access the EndpointCreator instance to add custom routes

# Note: router.routes[0].endpoint.__self__ accesses the internal creator instance

router_creator = router.routes[0].endpoint.__self__

router_creator.add_custom_route(
    endpoint=special_report,
    methods=["GET"],
    path="/admin/report",
    dependencies=[verify_admin],
    tags=["admin"],
    summary="Admin-only report",
)

The dependencies list passed to add_custom_route undergoes the same validation and wrapping process as standard CRUD dependencies.

Dynamic Dependencies and Multi-Tenant Sessions

Dependencies can return values that FastCRUD passes as named parameters to your endpoint functions. This enables advanced patterns such as tenant-aware database sessions.


# tenant_deps.py

from fastapi import Depends, Header

def get_tenant_db(tenant_id: str = Header(...)):
    # Resolve the appropriate async session for the tenant

    return get_async_session_for_tenant(tenant_id)

# Apply only to the list endpoint

router = crud_router(
    ...,
    read_multi_deps=[get_tenant_db],
)

When get_tenant_db resolves, FastCRUD passes the returned session object as a parameter named tenant_db to the read-multi endpoint, alongside the standard db session.

Summary

  • FastCRUD accepts custom dependencies through six operation-specific parameters: create_deps, read_deps, read_multi_deps, update_deps, delete_deps, and db_delete_deps
  • Dependencies are validated and wrapped in fastapi.Depends by the inject_dependencies function located in fastcrud/fastapi_dependencies.py at lines 174-188
  • Custom routes added via EndpointCreator.add_custom_route support dependency injection through the dependencies parameter, processed at lines 71-79 of fastcrud/endpoint/endpoint_creator.py
  • Dependencies are resolved once at router construction time, ensuring zero runtime overhead for dependency validation
  • Returned dependency values are injected as named parameters into endpoint functions, enabling patterns like multi-tenant database routing

Frequently Asked Questions

Can I use the same dependency for all CRUD operations?

Yes. Pass the same callable to all six dependency parameters (create_deps, read_deps, read_multi_deps, update_deps, delete_deps, db_delete_deps) when calling crud_router. FastCRUD will wrap the callable in Depends for each respective endpoint, ensuring consistent authentication or logging across all operations.

How do I add dependencies only to specific endpoints?

Supply the dependency list only to the specific parameter corresponding to the desired operation. For example, pass your authentication callable only to delete_deps and db_delete_deps if only delete operations require elevated privileges. Leave other dependency parameters empty or omitted to use FastCRUD's default behavior for those endpoints.

What happens if a dependency returns a value?

FastAPI injects the return value as a keyword argument to your endpoint function using the dependency function's name as the parameter name. If your dependency function is named get_current_user, the endpoint receives a parameter current_user containing the resolved value. This works for both standard CRUD endpoints and custom routes added via add_custom_route.

Do custom dependencies conflict with FastCRUD's automatic database session injection?

No. FastCRUD manages its own database session dependencies internally while processing your custom dependencies separately. The inject_dependencies utility merges both sets without conflict, ensuring your custom callables receive their resolved values alongside the standard db session parameter that FastCRUD generates automatically.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →