[{"data":1,"prerenderedAt":90},["ShallowReactive",2],{"qa-\u002Ffastapi\u002Fdependency-injection\u002Fdepends-basics":3},{"page":4,"siblings":81,"blog":73},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":19,"order":20,"path":21,"questions":22,"questionsCount":72,"related":73,"seo":74,"seoDescription":75,"stem":76,"subtopic":6,"topic":77,"topicSlug":78,"updated":79,"__hash__":80},"qa\u002Ffastapi\u002Fdependency-injection\u002Fdepends-basics.md","Depends Basics",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"medium","md","FastAPI","fastapi",{},true,1,"\u002Ffastapi\u002Fdependency-injection\u002Fdepends-basics",[23,28,32,36,40,44,48,52,56,60,64,68],{"id":24,"difficulty":25,"q":26,"a":27},"depends-basics","easy","What is `Depends()` in FastAPI and why is it useful?","`Depends(fn)` tells FastAPI to call `fn`, pass any of its own parameters through\nthe same injection system, and give the **result** to the handler as the argument.\n\n```python\nfrom fastapi import Depends, FastAPI\n\napp = FastAPI()\n\ndef get_query(q: str | None = None):\n    return q\n\n@app.get(\"\u002Fitems\")\nasync def list_items(query: str | None = Depends(get_query)):\n    return {\"q\": query}\n```\n\nBenefits:\n- **Reusable logic** (auth, DB sessions, pagination) across many handlers.\n- **Testable** — swap dependencies via `app.dependency_overrides`.\n- **Recursive** — a dependency can itself declare `Depends()`.\n\nRule of thumb: extract any logic that repeats across handlers into a dependency\nfunction; if it's in more than two handlers, it probably belongs in a dep.\n",{"id":29,"difficulty":25,"q":30,"a":31},"dependency-parameters","Can a dependency function accept its own parameters (path, query, headers)?","Yes — dependency functions participate in the same parameter extraction system\nas route handlers. They can declare path params, query params, headers, cookies,\nand other `Depends()`.\n\n```python\nfrom fastapi import Depends, Query\n\ndef pagination(\n    page: int = Query(ge=1, default=1),\n    size: int = Query(ge=1, le=100, default=20),\n) -> dict:\n    return {\"skip\": (page - 1) * size, \"limit\": size}\n\n@app.get(\"\u002Fusers\")\nasync def list_users(paging: dict = Depends(pagination)):\n    return await db.get_users(**paging)\n\n@app.get(\"\u002Forders\")\nasync def list_orders(paging: dict = Depends(pagination)):\n    return await db.get_orders(**paging)\n```\n\nRule of thumb: put shared query parameters (pagination, sorting, filtering) into\na dependency class or function — define once, reuse everywhere.\n",{"id":33,"difficulty":14,"q":34,"a":35},"sub-dependencies","Can a dependency depend on another dependency (sub-dependencies)?","Yes — FastAPI resolves the full dependency graph recursively. Sub-dependencies\nare resolved before the dependencies that need them.\n\n```python\ndef get_db():\n    ...\n    yield session\n\ndef get_current_user(db = Depends(get_db)):\n    user = db.query(User).first()\n    return user\n\ndef require_admin(user = Depends(get_current_user)):\n    if not user.is_admin:\n        raise HTTPException(403, \"Admin only\")\n    return user\n\n@app.delete(\"\u002Fusers\u002F{id}\")\nasync def delete_user(id: int, admin = Depends(require_admin)):\n    ...\n```\n\nFastAPI calls `get_db → get_current_user → require_admin` in order, caching each\nresult within the request.\n\nRule of thumb: chain dependencies to encode privilege escalation cleanly —\n`require_admin` composes `get_current_user` which composes `get_db`.\n",{"id":37,"difficulty":14,"q":38,"a":39},"dependency-caching","If two dependencies declare `Depends(get_db)`, how many times is `get_db` called?","**Once per request** (by default). FastAPI caches dependency results within a\nsingle request — the same object is passed to both dependants.\n\n```python\ndef get_db():\n    print(\"get_db called\")\n    yield session\n\ndef dep_a(db = Depends(get_db)): ...\ndef dep_b(db = Depends(get_db)): ...\n\n@app.get(\"\u002F\")\nasync def handler(a = Depends(dep_a), b = Depends(dep_b)):\n    # \"get_db called\" prints once, not twice\n    ...\n```\n\nTo force a fresh call (bypass cache):\n```python\nDepends(get_db, use_cache=False)\n```\n\nRule of thumb: rely on caching to share a single DB session across all\ndependencies in a request — it prevents phantom double-writes or double-reads.\n",{"id":41,"difficulty":14,"q":42,"a":43},"class-based-dep","How do you create a class-based dependency in FastAPI?","Define a class with `__init__` taking FastAPI-injectable parameters, then\nuse the class itself (not an instance) as the argument to `Depends`:\n\n```python\nfrom fastapi import Depends, Query\n\nclass PaginationDep:\n    def __init__(\n        self,\n        page: int = Query(ge=1, default=1),\n        size: int = Query(ge=1, le=100, default=20),\n    ):\n        self.skip = (page - 1) * size\n        self.limit = size\n\n@app.get(\"\u002Fitems\")\nasync def list_items(paging: PaginationDep = Depends()):\n    return await db.get(skip=paging.skip, limit=paging.limit)\n```\n\n`Depends()` (with no argument) is shorthand for `Depends(PaginationDep)` when\nthe type annotation is already the class.\n\nRule of thumb: use class-based dependencies for multi-parameter groups (pagination,\nfiltering) — they're more readable than a function returning a tuple of values.\n",{"id":45,"difficulty":14,"q":46,"a":47},"callable-instance-dep","Can a callable object instance be used as a FastAPI dependency?","Yes — any callable can be a dependency, including instances with `__call__`:\n\n```python\nclass VerifyToken:\n    def __init__(self, required_scope: str):\n        self.required_scope = required_scope\n\n    def __call__(self, token: str = Depends(oauth2_scheme)):\n        payload = decode_jwt(token)\n        if self.required_scope not in payload.get(\"scopes\", []):\n            raise HTTPException(403, \"Insufficient scope\")\n        return payload\n\nverify_read  = VerifyToken(\"read\")\nverify_write = VerifyToken(\"write\")\n\n@app.get(\"\u002Fitems\", dependencies=[Depends(verify_read)])\nasync def list_items(): ...\n\n@app.post(\"\u002Fitems\", dependencies=[Depends(verify_write)])\nasync def create_item(): ...\n```\n\nRule of thumb: use callable instances when a dependency needs to be parameterised\nat definition time (scope, role, feature flag) — it avoids writing multiple\nnear-identical dependency functions.\n",{"id":49,"difficulty":25,"q":50,"a":51},"depends-shorthand","What is the `Depends()` shorthand and when can you use it?","When the type annotation already names the dependency class, you can write\n`Depends()` (no argument) and FastAPI infers the class from the annotation:\n\n```python\nclass CommonQueryParams:\n    def __init__(self, q: str | None = None, skip: int = 0):\n        self.q = q\n        self.skip = skip\n\n@app.get(\"\u002Fitems\")\nasync def list_items(commons: CommonQueryParams = Depends()):\n    #                                                  ^^^ shorthand\n    return commons.__dict__\n```\n\nThis only works in Python 3.10+ (or with `from __future__ import annotations`)\nand requires the annotation to be a class directly, not a string or `Optional`.\n\nRule of thumb: use the shorthand for class-based deps to reduce repetition;\nuse the explicit `Depends(SomeFunction)` for function-based deps (no shorthand there).\n",{"id":53,"difficulty":14,"q":54,"a":55},"path-operation-dependencies","How do you apply a dependency to a route without using its return value?","Pass it to the `dependencies=` list in the route decorator. The dependency runs\nbut its return value is discarded.\n\n```python\nfrom fastapi import Depends\n\nasync def rate_limit():\n    if too_many_requests():\n        raise HTTPException(429, \"Too many requests\")\n\n@app.get(\"\u002Fitems\", dependencies=[Depends(rate_limit)])\nasync def list_items():\n    return []\n```\n\nThe same dependency can be applied at the router level:\n```python\nrouter = APIRouter(dependencies=[Depends(rate_limit)])\n```\n\nRule of thumb: use `dependencies=[...]` for side-effect deps (auth checks,\nrate limiting, audit logging) where the return value is not needed in the handler.\n",{"id":57,"difficulty":14,"q":58,"a":59},"global-dependencies","How do you apply a dependency globally to every route in the app?","Pass `dependencies` to the `FastAPI()` constructor:\n\n```python\nfrom fastapi import FastAPI, Depends\n\nasync def verify_api_key(x_api_key: str = Header()):\n    if x_api_key != settings.api_key:\n        raise HTTPException(401)\n\napp = FastAPI(dependencies=[Depends(verify_api_key)])\n```\n\nEvery single route in the app now runs `verify_api_key` first. To exclude\nspecific routes (e.g., the `\u002Fhealth` check), structure them under a different\nrouter that doesn't inherit the global dependency.\n\nRule of thumb: global dependencies are powerful but inflexible — prefer\nrouter-level dependencies so you can have public and protected route groups.\n",{"id":61,"difficulty":25,"q":62,"a":63},"dependency-return-type","What types can a dependency function return?","Any Python value — FastAPI passes whatever the function returns to the handler\nparameter:\n\n```python\n# returns a simple value\ndef current_user_id(token: str = Depends(oauth2_scheme)) -> int:\n    return decode_jwt(token)[\"sub\"]\n\n# returns a Pydantic model\ndef current_user(token: str = Depends(oauth2_scheme)) -> User:\n    return User.model_validate(decode_jwt(token))\n\n# returns None (side-effect dep)\ndef check_rate_limit():\n    if over_limit():\n        raise HTTPException(429)\n\n@app.get(\"\u002Fme\")\nasync def me(user: User = Depends(current_user)):\n    return user\n```\n\nRule of thumb: annotate the return type of dependency functions — it documents\nwhat the handler receives and helps type checkers catch mismatches.\n",{"id":65,"difficulty":14,"q":66,"a":67},"dependency-exception","What happens if a dependency raises an `HTTPException`?","The exception propagates up through the dependency chain and FastAPI returns the\nerror response to the client — the handler never runs.\n\n```python\nasync def get_current_user(token: str = Depends(oauth2_scheme)):\n    try:\n        payload = jwt.decode(token, SECRET_KEY, algorithms=[\"HS256\"])\n    except JWTError:\n        raise HTTPException(\n            status_code=401,\n            detail=\"Invalid token\",\n            headers={\"WWW-Authenticate\": \"Bearer\"},\n        )\n    return payload\n\n@app.get(\"\u002Fme\")\nasync def me(user: dict = Depends(get_current_user)):\n    return user   # only reached if get_current_user doesn't raise\n```\n\nRule of thumb: raise `HTTPException` in dependencies rather than returning\nsentinel values — the handler should never need to check \"did the dep succeed?\".\n",{"id":69,"difficulty":14,"q":70,"a":71},"testing-dependency-override","How do you override a dependency in tests?","Use `app.dependency_overrides` dict. The key is the original function; the value\nis the replacement callable:\n\n```python\nfrom fastapi.testclient import TestClient\nfrom app.main import app\nfrom app.dependencies import get_current_user\n\ndef mock_user():\n    return {\"sub\": 1, \"role\": \"admin\"}\n\napp.dependency_overrides[get_current_user] = mock_user\n\nclient = TestClient(app)\n\ndef test_admin_endpoint():\n    resp = client.get(\"\u002Fadmin\u002Fstats\")\n    assert resp.status_code == 200\n\n# Clean up after the test\napp.dependency_overrides.clear()\n```\n\nRule of thumb: always clear `dependency_overrides` after each test — a stale\noverride in one test silently affects subsequent tests.\n",12,null,{"description":11},"FastAPI dependency injection interview questions — Depends(), shared sub-dependencies, caching, class-based dependencies and path operation dependencies.","fastapi\u002Fdependency-injection\u002Fdepends-basics","Dependency Injection","dependency-injection","2026-06-20","mPp69gCF-1heEe8Jgp4KWGXtAoVklZZTpM7ZiXN4AS8",[82,83,86],{"subtopic":6,"path":21,"order":20},{"subtopic":84,"path":85,"order":12},"Advanced Dependencies","\u002Ffastapi\u002Fdependency-injection\u002Fadvanced-deps",{"subtopic":87,"path":88,"order":89},"Lifespan & App State","\u002Ffastapi\u002Fdependency-injection\u002Flifespan",3,1782244112914]