Compare commits

...
2 Commits
47 changed files with 6009 additions and 1300 deletions
+1 -1
View File
@@ -1 +1 @@
v4.1
v5.0
BIN
View File
Binary file not shown.
-1
View File
File diff suppressed because one or more lines are too long
-90
View File
@@ -1,90 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/module/cli/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/module/crud/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/module/db/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/module/dependencies/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/module/exceptions/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/module/fixtures/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/module/logger/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/module/metrics/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/module/models/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/module/pytest/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/module/schemas/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/module/security/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/reference/cli/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/reference/crud/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/reference/db/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/reference/dependencies/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/reference/exceptions/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/reference/fixtures/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/reference/logger/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/reference/metrics/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/reference/models/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/reference/pytest/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/reference/schemas/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/reference/security/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/examples/pagination-search/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/migration/v4/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/migration/v3/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v4.0/migration/v2/</loc>
</url>
</urlset>
+119 -43
View File
@@ -18,8 +18,8 @@
<link rel="icon" href="/v4.0/assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<link rel="icon" href="/v5.0/assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.43">
@@ -30,12 +30,12 @@
<link rel="stylesheet" href="/v4.0/assets/stylesheets/modern/main.fba56155.min.css">
<link rel="stylesheet" href="/v5.0/assets/stylesheets/modern/main.fba56155.min.css">
<link rel="stylesheet" href="/v4.0/assets/stylesheets/modern/palette.dfe2e883.min.css">
<link rel="stylesheet" href="/v5.0/assets/stylesheets/modern/palette.dfe2e883.min.css">
@@ -54,7 +54,7 @@
<script>__md_scope=new URL("/v4.0",location),__md_scope.pathname.endsWith("/")||(__md_scope=new URL(__md_scope.pathname+"/",location)),__md_hash=e=>[...e].reduce(((e,t)=>(e<<5)-e+t.charCodeAt(0)),0),__md_get=(e,t=localStorage,_=__md_scope)=>JSON.parse(t.getItem(_.pathname+"."+e)),__md_set=(e,t,_=localStorage,a=__md_scope)=>{try{_.setItem(a.pathname+"."+e,JSON.stringify(t))}catch(e){}},document.documentElement.setAttribute("data-platform",navigator.platform)</script>
<script>__md_scope=new URL("/v5.0",location),__md_scope.pathname.endsWith("/")||(__md_scope=new URL(__md_scope.pathname+"/",location)),__md_hash=e=>[...e].reduce(((e,t)=>(e<<5)-e+t.charCodeAt(0)),0),__md_get=(e,t=localStorage,_=__md_scope)=>JSON.parse(t.getItem(_.pathname+"."+e)),__md_set=(e,t,_=localStorage,a=__md_scope)=>{try{_.setItem(a.pathname+"."+e,JSON.stringify(t))}catch(e){}},document.documentElement.setAttribute("data-platform",navigator.platform)</script>
@@ -102,7 +102,7 @@
<header class="md-header" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href="/v4.0/" title="FastAPI Toolsets" class="md-header__button md-logo" aria-label="FastAPI Toolsets" data-md-component="logo">
<a href="/v5.0/" title="FastAPI Toolsets" class="md-header__button md-logo" aria-label="FastAPI Toolsets" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-book-open" viewBox="0 0 24 24"><path d="M12 7v14M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/></svg>
@@ -206,7 +206,7 @@
<li class="md-tabs__item">
<a href="/v4.0/" class="md-tabs__link">
<a href="/v5.0/" class="md-tabs__link">
Home
@@ -222,9 +222,38 @@
<li class="md-tabs__item">
<a href="/v4.0/module/cli/" class="md-tabs__link">
<a href="/v5.0/module/cli/" class="md-tabs__link">
Modules
@@ -241,9 +270,38 @@
<li class="md-tabs__item">
<a href="/v4.0/reference/cli/" class="md-tabs__link">
<a href="/v5.0/reference/cli/" class="md-tabs__link">
Reference
@@ -260,9 +318,16 @@
<li class="md-tabs__item">
<a href="/v4.0/examples/pagination-search/" class="md-tabs__link">
<a href="/v5.0/examples/pagination-search/" class="md-tabs__link">
Examples
@@ -278,10 +343,21 @@
<li class="md-tabs__item">
<a href="/v4.0/migration/v4/" class="md-tabs__link">
<a href="/v5.0/migration/v4/" class="md-tabs__link">
Migration
@@ -330,7 +406,7 @@
<nav class="md-nav md-nav--primary md-nav--lifted" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="/v4.0/" title="FastAPI Toolsets" class="md-nav__button md-logo" aria-label="FastAPI Toolsets" data-md-component="logo">
<a href="/v5.0/" title="FastAPI Toolsets" class="md-nav__button md-logo" aria-label="FastAPI Toolsets" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-book-open" viewBox="0 0 24 24"><path d="M12 7v14M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/></svg>
@@ -360,7 +436,7 @@
<li class="md-nav__item">
<a href="/v4.0/" class="md-nav__link">
<a href="/v5.0/" class="md-nav__link">
@@ -462,7 +538,7 @@
<li class="md-nav__item">
<a href="/v4.0/module/cli/" class="md-nav__link">
<a href="/v5.0/module/cli/" class="md-nav__link">
@@ -489,7 +565,7 @@
<li class="md-nav__item">
<a href="/v4.0/module/crud/" class="md-nav__link">
<a href="/v5.0/module/crud/" class="md-nav__link">
@@ -516,7 +592,7 @@
<li class="md-nav__item">
<a href="/v4.0/module/db/" class="md-nav__link">
<a href="/v5.0/module/db/" class="md-nav__link">
@@ -543,7 +619,7 @@
<li class="md-nav__item">
<a href="/v4.0/module/dependencies/" class="md-nav__link">
<a href="/v5.0/module/dependencies/" class="md-nav__link">
@@ -570,7 +646,7 @@
<li class="md-nav__item">
<a href="/v4.0/module/exceptions/" class="md-nav__link">
<a href="/v5.0/module/exceptions/" class="md-nav__link">
@@ -597,7 +673,7 @@
<li class="md-nav__item">
<a href="/v4.0/module/fixtures/" class="md-nav__link">
<a href="/v5.0/module/fixtures/" class="md-nav__link">
@@ -624,7 +700,7 @@
<li class="md-nav__item">
<a href="/v4.0/module/logger/" class="md-nav__link">
<a href="/v5.0/module/logger/" class="md-nav__link">
@@ -651,7 +727,7 @@
<li class="md-nav__item">
<a href="/v4.0/module/metrics/" class="md-nav__link">
<a href="/v5.0/module/metrics/" class="md-nav__link">
@@ -678,7 +754,7 @@
<li class="md-nav__item">
<a href="/v4.0/module/models/" class="md-nav__link">
<a href="/v5.0/module/models/" class="md-nav__link">
@@ -705,7 +781,7 @@
<li class="md-nav__item">
<a href="/v4.0/module/pytest/" class="md-nav__link">
<a href="/v5.0/module/pytest/" class="md-nav__link">
@@ -732,7 +808,7 @@
<li class="md-nav__item">
<a href="/v4.0/module/schemas/" class="md-nav__link">
<a href="/v5.0/module/schemas/" class="md-nav__link">
@@ -759,7 +835,7 @@
<li class="md-nav__item">
<a href="/v4.0/module/security/" class="md-nav__link">
<a href="/v5.0/module/security/" class="md-nav__link">
@@ -869,7 +945,7 @@
<li class="md-nav__item">
<a href="/v4.0/reference/cli/" class="md-nav__link">
<a href="/v5.0/reference/cli/" class="md-nav__link">
@@ -896,7 +972,7 @@
<li class="md-nav__item">
<a href="/v4.0/reference/crud/" class="md-nav__link">
<a href="/v5.0/reference/crud/" class="md-nav__link">
@@ -923,7 +999,7 @@
<li class="md-nav__item">
<a href="/v4.0/reference/db/" class="md-nav__link">
<a href="/v5.0/reference/db/" class="md-nav__link">
@@ -950,7 +1026,7 @@
<li class="md-nav__item">
<a href="/v4.0/reference/dependencies/" class="md-nav__link">
<a href="/v5.0/reference/dependencies/" class="md-nav__link">
@@ -977,7 +1053,7 @@
<li class="md-nav__item">
<a href="/v4.0/reference/exceptions/" class="md-nav__link">
<a href="/v5.0/reference/exceptions/" class="md-nav__link">
@@ -1004,7 +1080,7 @@
<li class="md-nav__item">
<a href="/v4.0/reference/fixtures/" class="md-nav__link">
<a href="/v5.0/reference/fixtures/" class="md-nav__link">
@@ -1031,7 +1107,7 @@
<li class="md-nav__item">
<a href="/v4.0/reference/logger/" class="md-nav__link">
<a href="/v5.0/reference/logger/" class="md-nav__link">
@@ -1058,7 +1134,7 @@
<li class="md-nav__item">
<a href="/v4.0/reference/metrics/" class="md-nav__link">
<a href="/v5.0/reference/metrics/" class="md-nav__link">
@@ -1085,7 +1161,7 @@
<li class="md-nav__item">
<a href="/v4.0/reference/models/" class="md-nav__link">
<a href="/v5.0/reference/models/" class="md-nav__link">
@@ -1112,7 +1188,7 @@
<li class="md-nav__item">
<a href="/v4.0/reference/pytest/" class="md-nav__link">
<a href="/v5.0/reference/pytest/" class="md-nav__link">
@@ -1139,7 +1215,7 @@
<li class="md-nav__item">
<a href="/v4.0/reference/schemas/" class="md-nav__link">
<a href="/v5.0/reference/schemas/" class="md-nav__link">
@@ -1166,7 +1242,7 @@
<li class="md-nav__item">
<a href="/v4.0/reference/security/" class="md-nav__link">
<a href="/v5.0/reference/security/" class="md-nav__link">
@@ -1254,7 +1330,7 @@
<li class="md-nav__item">
<a href="/v4.0/examples/pagination-search/" class="md-nav__link">
<a href="/v5.0/examples/pagination-search/" class="md-nav__link">
@@ -1346,7 +1422,7 @@
<li class="md-nav__item">
<a href="/v4.0/migration/v4/" class="md-nav__link">
<a href="/v5.0/migration/v4/" class="md-nav__link">
@@ -1373,7 +1449,7 @@
<li class="md-nav__item">
<a href="/v4.0/migration/v3/" class="md-nav__link">
<a href="/v5.0/migration/v3/" class="md-nav__link">
@@ -1400,7 +1476,7 @@
<li class="md-nav__item">
<a href="/v4.0/migration/v2/" class="md-nav__link">
<a href="/v5.0/migration/v2/" class="md-nav__link">
@@ -1549,10 +1625,10 @@
<script id="__config" type="application/json">{"annotate":null,"base":"/v4.0","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"/v4.0/assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script id="__config" type="application/json">{"annotate":null,"base":"/v5.0","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"/v5.0/assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="/v4.0/assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="/v5.0/assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

File diff suppressed because one or more lines are too long
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/examples/pagination-search/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/examples/pagination-search/">
<link rel="prev" href="../../reference/security/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -229,6 +229,35 @@
<li class="md-tabs__item">
<a href="../../module/cli/" class="md-tabs__link">
@@ -248,6 +277,35 @@
<li class="md-tabs__item">
<a href="../../reference/cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="././" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -1813,6 +1889,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -1828,9 +1905,17 @@
<li class="md-path__item">
<a href="././" class="md-path__link">
<span class="md-ellipsis">
Examples
</span>
@@ -1941,20 +2026,17 @@
<div class="language-python highlight"><span class="filename">db.py</span><pre><span></span><code><span id="__span-3-1"><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Annotated</span>
</span><span id="__span-3-2"><a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a>
</span><span id="__span-3-3"><a id="__codelineno-3-3" name="__codelineno-3-3" href="#__codelineno-3-3"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi</span><span class="w"> </span><span class="kn">import</span> <span class="n">Depends</span>
</span><span id="__span-3-4"><a id="__codelineno-3-4" name="__codelineno-3-4" href="#__codelineno-3-4"></a><span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy.ext.asyncio</span><span class="w"> </span><span class="kn">import</span> <span class="n">AsyncSession</span><span class="p">,</span> <span class="n">async_sessionmaker</span><span class="p">,</span> <span class="n">create_async_engine</span>
</span><span id="__span-3-4"><a id="__codelineno-3-4" name="__codelineno-3-4" href="#__codelineno-3-4"></a><span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy.ext.asyncio</span><span class="w"> </span><span class="kn">import</span> <span class="n">AsyncSession</span>
</span><span id="__span-3-5"><a id="__codelineno-3-5" name="__codelineno-3-5" href="#__codelineno-3-5"></a>
</span><span id="__span-3-6"><a id="__codelineno-3-6" name="__codelineno-3-6" href="#__codelineno-3-6"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_db_context</span><span class="p">,</span> <span class="n">create_db_dependency</span>
</span><span id="__span-3-6"><a id="__codelineno-3-6" name="__codelineno-3-6" href="#__codelineno-3-6"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">Database</span>
</span><span id="__span-3-7"><a id="__codelineno-3-7" name="__codelineno-3-7" href="#__codelineno-3-7"></a>
</span><span id="__span-3-8"><a id="__codelineno-3-8" name="__codelineno-3-8" href="#__codelineno-3-8"></a><span class="n">DATABASE_URL</span> <span class="o">=</span> <span class="s2">&quot;postgresql+asyncpg://postgres:postgres@localhost:5432/postgres&quot;</span>
</span><span id="__span-3-9"><a id="__codelineno-3-9" name="__codelineno-3-9" href="#__codelineno-3-9"></a>
</span><span id="__span-3-10"><a id="__codelineno-3-10" name="__codelineno-3-10" href="#__codelineno-3-10"></a><span class="n">engine</span> <span class="o">=</span> <span class="n">create_async_engine</span><span class="p">(</span><span class="n">url</span><span class="o">=</span><span class="n">DATABASE_URL</span><span class="p">,</span> <span class="n">future</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="__span-3-11"><a id="__codelineno-3-11" name="__codelineno-3-11" href="#__codelineno-3-11"></a><span class="n">async_session_maker</span> <span class="o">=</span> <span class="n">async_sessionmaker</span><span class="p">(</span><span class="n">bind</span><span class="o">=</span><span class="n">engine</span><span class="p">,</span> <span class="n">expire_on_commit</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
</span><span id="__span-3-12"><a id="__codelineno-3-12" name="__codelineno-3-12" href="#__codelineno-3-12"></a>
</span><span id="__span-3-13"><a id="__codelineno-3-13" name="__codelineno-3-13" href="#__codelineno-3-13"></a><span class="n">get_db</span> <span class="o">=</span> <span class="n">create_db_dependency</span><span class="p">(</span><span class="n">session_maker</span><span class="o">=</span><span class="n">async_session_maker</span><span class="p">)</span>
</span><span id="__span-3-14"><a id="__codelineno-3-14" name="__codelineno-3-14" href="#__codelineno-3-14"></a><span class="n">get_db_context</span> <span class="o">=</span> <span class="n">create_db_context</span><span class="p">(</span><span class="n">session_maker</span><span class="o">=</span><span class="n">async_session_maker</span><span class="p">)</span>
</span><span id="__span-3-15"><a id="__codelineno-3-15" name="__codelineno-3-15" href="#__codelineno-3-15"></a>
</span><span id="__span-3-16"><a id="__codelineno-3-16" name="__codelineno-3-16" href="#__codelineno-3-16"></a>
</span><span id="__span-3-17"><a id="__codelineno-3-17" name="__codelineno-3-17" href="#__codelineno-3-17"></a><span class="n">SessionDep</span> <span class="o">=</span> <span class="n">Annotated</span><span class="p">[</span><span class="n">AsyncSession</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">get_db</span><span class="p">)]</span>
</span><span id="__span-3-10"><a id="__codelineno-3-10" name="__codelineno-3-10" href="#__codelineno-3-10"></a><span class="n">db</span> <span class="o">=</span> <span class="n">Database</span><span class="p">(</span><span class="n">url</span><span class="o">=</span><span class="n">DATABASE_URL</span><span class="p">)</span>
</span><span id="__span-3-11"><a id="__codelineno-3-11" name="__codelineno-3-11" href="#__codelineno-3-11"></a>
</span><span id="__span-3-12"><a id="__codelineno-3-12" name="__codelineno-3-12" href="#__codelineno-3-12"></a><span class="n">get_db</span> <span class="o">=</span> <span class="n">db</span>
</span><span id="__span-3-13"><a id="__codelineno-3-13" name="__codelineno-3-13" href="#__codelineno-3-13"></a>
</span><span id="__span-3-14"><a id="__codelineno-3-14" name="__codelineno-3-14" href="#__codelineno-3-14"></a><span class="n">SessionDep</span> <span class="o">=</span> <span class="n">Annotated</span><span class="p">[</span><span class="n">AsyncSession</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">db</span><span class="p">)]</span>
</span></code></pre></div>
<div class="admonition info">
<p class="admonition-title">Deploy a Postgres DB with docker</p>
@@ -1966,11 +2048,13 @@
</span><span id="__span-5-2"><a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a>
</span><span id="__span-5-3"><a id="__codelineno-5-3" name="__codelineno-5-3" href="#__codelineno-5-3"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.exceptions</span><span class="w"> </span><span class="kn">import</span> <span class="n">init_exceptions_handlers</span>
</span><span id="__span-5-4"><a id="__codelineno-5-4" name="__codelineno-5-4" href="#__codelineno-5-4"></a>
</span><span id="__span-5-5"><a id="__codelineno-5-5" name="__codelineno-5-5" href="#__codelineno-5-5"></a><span class="kn">from</span><span class="w"> </span><span class="nn">.routes</span><span class="w"> </span><span class="kn">import</span> <span class="n">router</span>
</span><span id="__span-5-6"><a id="__codelineno-5-6" name="__codelineno-5-6" href="#__codelineno-5-6"></a>
</span><span id="__span-5-7"><a id="__codelineno-5-7" name="__codelineno-5-7" href="#__codelineno-5-7"></a><span class="n">app</span> <span class="o">=</span> <span class="n">FastAPI</span><span class="p">()</span>
</span><span id="__span-5-8"><a id="__codelineno-5-8" name="__codelineno-5-8" href="#__codelineno-5-8"></a><span class="n">init_exceptions_handlers</span><span class="p">(</span><span class="n">app</span><span class="o">=</span><span class="n">app</span><span class="p">)</span>
</span><span id="__span-5-9"><a id="__codelineno-5-9" name="__codelineno-5-9" href="#__codelineno-5-9"></a><span class="n">app</span><span class="o">.</span><span class="n">include_router</span><span class="p">(</span><span class="n">router</span><span class="o">=</span><span class="n">router</span><span class="p">)</span>
</span><span id="__span-5-5"><a id="__codelineno-5-5" name="__codelineno-5-5" href="#__codelineno-5-5"></a><span class="kn">from</span><span class="w"> </span><span class="nn">.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">db</span>
</span><span id="__span-5-6"><a id="__codelineno-5-6" name="__codelineno-5-6" href="#__codelineno-5-6"></a><span class="kn">from</span><span class="w"> </span><span class="nn">.routes</span><span class="w"> </span><span class="kn">import</span> <span class="n">router</span>
</span><span id="__span-5-7"><a id="__codelineno-5-7" name="__codelineno-5-7" href="#__codelineno-5-7"></a>
</span><span id="__span-5-8"><a id="__codelineno-5-8" name="__codelineno-5-8" href="#__codelineno-5-8"></a><span class="n">app</span> <span class="o">=</span> <span class="n">FastAPI</span><span class="p">()</span>
</span><span id="__span-5-9"><a id="__codelineno-5-9" name="__codelineno-5-9" href="#__codelineno-5-9"></a><span class="n">db</span><span class="o">.</span><span class="n">install</span><span class="p">(</span><span class="n">app</span><span class="o">=</span><span class="n">app</span><span class="p">)</span>
</span><span id="__span-5-10"><a id="__codelineno-5-10" name="__codelineno-5-10" href="#__codelineno-5-10"></a><span class="n">init_exceptions_handlers</span><span class="p">(</span><span class="n">app</span><span class="o">=</span><span class="n">app</span><span class="p">)</span>
</span><span id="__span-5-11"><a id="__codelineno-5-11" name="__codelineno-5-11" href="#__codelineno-5-11"></a><span class="n">app</span><span class="o">.</span><span class="n">include_router</span><span class="p">(</span><span class="n">router</span><span class="o">=</span><span class="n">router</span><span class="p">)</span>
</span></code></pre></div>
<h2 id="routes">Routes<a class="headerlink" href="#routes" title="Permanent link">&para;</a></h2>
<div class="language-python highlight"><span class="filename">routes.py:1:16</span><pre><span></span><code><span id="__span-6-1"><a id="__codelineno-6-1" name="__codelineno-6-1" href="#__codelineno-6-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Annotated</span>
@@ -2246,7 +2330,7 @@
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
+79 -3
View File
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/">
@@ -23,7 +23,7 @@
<link rel="icon" href="./assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -229,6 +229,35 @@
<li class="md-tabs__item">
<a href="./module/cli/" class="md-tabs__link">
@@ -248,6 +277,35 @@
<li class="md-tabs__item">
<a href="./reference/cli/" class="md-tabs__link">
@@ -267,6 +325,13 @@
<li class="md-tabs__item">
<a href="./examples/pagination-search/" class="md-tabs__link">
@@ -285,6 +350,17 @@
<li class="md-tabs__item">
@@ -1865,7 +1941,7 @@
<script id="__config" type="application/json">{"annotate":null,"base":".","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"./assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="./assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="./assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/migration/v2/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/migration/v2/">
<link rel="prev" href="../v3/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -229,6 +229,35 @@
<li class="md-tabs__item">
<a href="../../module/cli/" class="md-tabs__link">
@@ -248,6 +277,35 @@
<li class="md-tabs__item">
<a href="../../reference/cli/" class="md-tabs__link">
@@ -267,6 +325,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item md-tabs__item--active">
@@ -1815,6 +1891,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -1830,9 +1907,21 @@
<li class="md-path__item">
<a href="../v4/" class="md-path__link">
<span class="md-ellipsis">
Migration
</span>
@@ -2079,7 +2168,7 @@
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/migration/v3/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/migration/v3/">
<link rel="prev" href="../v4/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -229,6 +229,35 @@
<li class="md-tabs__item">
<a href="../../module/cli/" class="md-tabs__link">
@@ -248,6 +277,35 @@
<li class="md-tabs__item">
<a href="../../reference/cli/" class="md-tabs__link">
@@ -267,6 +325,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item md-tabs__item--active">
@@ -1737,6 +1813,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -1752,9 +1829,21 @@
<li class="md-path__item">
<a href="../v4/" class="md-path__link">
<span class="md-ellipsis">
Migration
</span>
@@ -2067,7 +2156,7 @@
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/migration/v4/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/migration/v4/">
<link rel="prev" href="../../examples/pagination-search/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -229,6 +229,35 @@
<li class="md-tabs__item">
<a href="../../module/cli/" class="md-tabs__link">
@@ -248,6 +277,35 @@
<li class="md-tabs__item">
<a href="../../reference/cli/" class="md-tabs__link">
@@ -267,6 +325,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item md-tabs__item--active">
@@ -1637,6 +1713,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -1652,9 +1729,21 @@
<li class="md-path__item">
<a href="././" class="md-path__link">
<span class="md-ellipsis">
Migration
</span>
@@ -1825,7 +1914,7 @@ The function creates and manages its own <strong>dedicated session</strong> inte
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/module/cli/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/module/cli/">
<link rel="prev" href="../..">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -231,6 +231,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="././" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item">
<a href="../../reference/cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -1691,6 +1767,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -1706,9 +1783,39 @@
<li class="md-path__item">
<a href="././" class="md-path__link">
<span class="md-ellipsis">
Modules
</span>
@@ -1919,7 +2026,7 @@
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/module/crud/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/module/crud/">
<link rel="prev" href="../cli/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -231,6 +231,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="../cli/" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item">
<a href="../../reference/cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -653,6 +729,17 @@
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#row-locking" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
Row locking
</span>
</span>
</a>
</li>
<li class="md-nav__item">
@@ -1918,6 +2005,17 @@
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#row-locking" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
Row locking
</span>
</span>
</a>
</li>
<li class="md-nav__item">
@@ -2125,6 +2223,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -2140,9 +2239,39 @@
<li class="md-path__item">
<a href="../cli/" class="md-path__link">
<span class="md-ellipsis">
Modules
</span>
@@ -2301,6 +2430,54 @@
<p>Use <code>first</code> when you only care about any one match and don't need uniqueness:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-8-1"><a id="__codelineno-8-1" name="__codelineno-8-1" href="#__codelineno-8-1"></a><span class="n">user</span> <span class="o">=</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">first</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="n">filters</span><span class="o">=</span><span class="p">[</span><span class="n">User</span><span class="o">.</span><span class="n">is_active</span> <span class="o">==</span> <span class="kc">True</span><span class="p">])</span>
</span></code></pre></div>
<h2 id="row-locking">Row locking<a class="headerlink" href="#row-locking" title="Permanent link">&para;</a></h2>
<p><code>get</code>, <code>get_or_none</code>, <code>first</code>, <code>get_multi</code>, and <code>update</code> all accept a <code>with_for_update</code> parameter that appends a <code>FOR UPDATE</code> clause to the underlying <code>SELECT</code>, preventing concurrent transactions from modifying the matched rows until the current transaction commits.</p>
<table>
<thead>
<tr>
<th>Value</th>
<th>SQL clause</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>False</code> (default)</td>
<td>no locking</td>
</tr>
<tr>
<td><code>True</code></td>
<td><code>FOR UPDATE</code></td>
</tr>
<tr>
<td><code>"nowait"</code></td>
<td><code>FOR UPDATE NOWAIT</code></td>
</tr>
<tr>
<td><code>"skip_locked"</code></td>
<td><code>FOR UPDATE SKIP LOCKED</code></td>
</tr>
</tbody>
</table>
<div class="language-python highlight"><pre><span></span><code><span id="__span-9-1"><a id="__codelineno-9-1" name="__codelineno-9-1" href="#__codelineno-9-1"></a><span class="c1"># Lock before reading — typical read-modify-write pattern</span>
</span><span id="__span-9-2"><a id="__codelineno-9-2" name="__codelineno-9-2" href="#__codelineno-9-2"></a><span class="n">user</span> <span class="o">=</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="p">[</span><span class="n">User</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">user_id</span><span class="p">],</span> <span class="n">with_for_update</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="__span-9-3"><a id="__codelineno-9-3" name="__codelineno-9-3" href="#__codelineno-9-3"></a>
</span><span id="__span-9-4"><a id="__codelineno-9-4" name="__codelineno-9-4" href="#__codelineno-9-4"></a><span class="c1"># Raise immediately if another transaction holds the lock</span>
</span><span id="__span-9-5"><a id="__codelineno-9-5" name="__codelineno-9-5" href="#__codelineno-9-5"></a><span class="n">user</span> <span class="o">=</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="p">[</span><span class="n">User</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">user_id</span><span class="p">],</span> <span class="n">with_for_update</span><span class="o">=</span><span class="s2">&quot;nowait&quot;</span><span class="p">)</span>
</span><span id="__span-9-6"><a id="__codelineno-9-6" name="__codelineno-9-6" href="#__codelineno-9-6"></a>
</span><span id="__span-9-7"><a id="__codelineno-9-7" name="__codelineno-9-7" href="#__codelineno-9-7"></a><span class="c1"># Skip rows already locked by another transaction (e.g. job queues)</span>
</span><span id="__span-9-8"><a id="__codelineno-9-8" name="__codelineno-9-8" href="#__codelineno-9-8"></a><span class="n">rows</span> <span class="o">=</span> <span class="k">await</span> <span class="n">JobCrud</span><span class="o">.</span><span class="n">get_multi</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">filters</span><span class="o">=</span><span class="p">[</span><span class="n">Job</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="s2">&quot;pending&quot;</span><span class="p">],</span> <span class="n">with_for_update</span><span class="o">=</span><span class="s2">&quot;skip_locked&quot;</span><span class="p">)</span>
</span><span id="__span-9-9"><a id="__codelineno-9-9" name="__codelineno-9-9" href="#__codelineno-9-9"></a>
</span><span id="__span-9-10"><a id="__codelineno-9-10" name="__codelineno-9-10" href="#__codelineno-9-10"></a><span class="c1"># Lock atomically as part of update (prevents race between SELECT and UPDATE)</span>
</span><span id="__span-9-11"><a id="__codelineno-9-11" name="__codelineno-9-11" href="#__codelineno-9-11"></a><span class="n">user</span> <span class="o">=</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">UserUpdate</span><span class="p">(</span><span class="n">credits</span><span class="o">=</span><span class="mi">10</span><span class="p">),</span> <span class="p">[</span><span class="n">User</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">user_id</span><span class="p">],</span> <span class="n">with_for_update</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span></code></pre></div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p><code>with_for_update</code> requires an open transaction. Wrap your call in <code>async with session.begin()</code> or use the <code>transaction</code> helper if you are not already inside one.</p>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p><code>NOWAIT</code> raises <code>sqlalchemy.exc.OperationalError</code> immediately if the row is locked rather than waiting.</p>
</div>
<h2 id="pagination">Pagination<a class="headerlink" href="#pagination" title="Permanent link">&para;</a></h2>
<div class="admonition info">
<p class="admonition-title">Added in <code>v1.1</code> (only offset_pagination via <code>paginate</code> if <code>&lt;v1.1</code>)</p>
@@ -2355,62 +2532,62 @@
</tbody>
</table>
<h3 id="offset-pagination">Offset pagination<a class="headerlink" href="#offset-pagination" title="Permanent link">&para;</a></h3>
<div class="language-python highlight"><pre><span></span><code><span id="__span-9-1"><a id="__codelineno-9-1" name="__codelineno-9-1" href="#__codelineno-9-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Annotated</span>
</span><span id="__span-9-2"><a id="__codelineno-9-2" name="__codelineno-9-2" href="#__codelineno-9-2"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi</span><span class="w"> </span><span class="kn">import</span> <span class="n">Depends</span>
</span><span id="__span-9-3"><a id="__codelineno-9-3" name="__codelineno-9-3" href="#__codelineno-9-3"></a>
</span><span id="__span-9-4"><a id="__codelineno-9-4" name="__codelineno-9-4" href="#__codelineno-9-4"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
</span><span id="__span-9-5"><a id="__codelineno-9-5" name="__codelineno-9-5" href="#__codelineno-9-5"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">get_users</span><span class="p">(</span>
</span><span id="__span-9-6"><a id="__codelineno-9-6" name="__codelineno-9-6" href="#__codelineno-9-6"></a> <span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span>
</span><span id="__span-9-7"><a id="__codelineno-9-7" name="__codelineno-9-7" href="#__codelineno-9-7"></a> <span class="n">params</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">dict</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate_params</span><span class="p">())],</span>
</span><span id="__span-9-8"><a id="__codelineno-9-8" name="__codelineno-9-8" href="#__codelineno-9-8"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">OffsetPaginatedResponse</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-9-9"><a id="__codelineno-9-9" name="__codelineno-9-9" href="#__codelineno-9-9"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">)</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-10-1"><a id="__codelineno-10-1" name="__codelineno-10-1" href="#__codelineno-10-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Annotated</span>
</span><span id="__span-10-2"><a id="__codelineno-10-2" name="__codelineno-10-2" href="#__codelineno-10-2"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi</span><span class="w"> </span><span class="kn">import</span> <span class="n">Depends</span>
</span><span id="__span-10-3"><a id="__codelineno-10-3" name="__codelineno-10-3" href="#__codelineno-10-3"></a>
</span><span id="__span-10-4"><a id="__codelineno-10-4" name="__codelineno-10-4" href="#__codelineno-10-4"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
</span><span id="__span-10-5"><a id="__codelineno-10-5" name="__codelineno-10-5" href="#__codelineno-10-5"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">get_users</span><span class="p">(</span>
</span><span id="__span-10-6"><a id="__codelineno-10-6" name="__codelineno-10-6" href="#__codelineno-10-6"></a> <span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span>
</span><span id="__span-10-7"><a id="__codelineno-10-7" name="__codelineno-10-7" href="#__codelineno-10-7"></a> <span class="n">params</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">dict</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate_params</span><span class="p">())],</span>
</span><span id="__span-10-8"><a id="__codelineno-10-8" name="__codelineno-10-8" href="#__codelineno-10-8"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">OffsetPaginatedResponse</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-10-9"><a id="__codelineno-10-9" name="__codelineno-10-9" href="#__codelineno-10-9"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">)</span>
</span></code></pre></div>
<p>The <a href="../../reference/crud/#fastapi_toolsets.crud.factory.AsyncCrud.offset_paginate"><code>offset_paginate</code></a> method returns an <a href="../../reference/schemas/#fastapi_toolsets.schemas.OffsetPaginatedResponse"><code>OffsetPaginatedResponse</code></a>:</p>
<div class="language-json highlight"><pre><span></span><code><span id="__span-10-1"><a id="__codelineno-10-1" name="__codelineno-10-1" href="#__codelineno-10-1"></a><span class="p">{</span>
</span><span id="__span-10-2"><a id="__codelineno-10-2" name="__codelineno-10-2" href="#__codelineno-10-2"></a><span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;SUCCESS&quot;</span><span class="p">,</span>
</span><span id="__span-10-3"><a id="__codelineno-10-3" name="__codelineno-10-3" href="#__codelineno-10-3"></a><span class="w"> </span><span class="nt">&quot;pagination_type&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;offset&quot;</span><span class="p">,</span>
</span><span id="__span-10-4"><a id="__codelineno-10-4" name="__codelineno-10-4" href="#__codelineno-10-4"></a><span class="w"> </span><span class="nt">&quot;data&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;...&quot;</span><span class="p">],</span>
</span><span id="__span-10-5"><a id="__codelineno-10-5" name="__codelineno-10-5" href="#__codelineno-10-5"></a><span class="w"> </span><span class="nt">&quot;pagination&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-10-6"><a id="__codelineno-10-6" name="__codelineno-10-6" href="#__codelineno-10-6"></a><span class="w"> </span><span class="nt">&quot;total_count&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">100</span><span class="p">,</span>
</span><span id="__span-10-7"><a id="__codelineno-10-7" name="__codelineno-10-7" href="#__codelineno-10-7"></a><span class="w"> </span><span class="nt">&quot;pages&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">5</span><span class="p">,</span>
</span><span id="__span-10-8"><a id="__codelineno-10-8" name="__codelineno-10-8" href="#__codelineno-10-8"></a><span class="w"> </span><span class="nt">&quot;page&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span>
</span><span id="__span-10-9"><a id="__codelineno-10-9" name="__codelineno-10-9" href="#__codelineno-10-9"></a><span class="w"> </span><span class="nt">&quot;items_per_page&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">20</span><span class="p">,</span>
</span><span id="__span-10-10"><a id="__codelineno-10-10" name="__codelineno-10-10" href="#__codelineno-10-10"></a><span class="w"> </span><span class="nt">&quot;has_more&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span>
</span><span id="__span-10-11"><a id="__codelineno-10-11" name="__codelineno-10-11" href="#__codelineno-10-11"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-10-12"><a id="__codelineno-10-12" name="__codelineno-10-12" href="#__codelineno-10-12"></a><span class="p">}</span>
<div class="language-json highlight"><pre><span></span><code><span id="__span-11-1"><a id="__codelineno-11-1" name="__codelineno-11-1" href="#__codelineno-11-1"></a><span class="p">{</span>
</span><span id="__span-11-2"><a id="__codelineno-11-2" name="__codelineno-11-2" href="#__codelineno-11-2"></a><span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;SUCCESS&quot;</span><span class="p">,</span>
</span><span id="__span-11-3"><a id="__codelineno-11-3" name="__codelineno-11-3" href="#__codelineno-11-3"></a><span class="w"> </span><span class="nt">&quot;pagination_type&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;offset&quot;</span><span class="p">,</span>
</span><span id="__span-11-4"><a id="__codelineno-11-4" name="__codelineno-11-4" href="#__codelineno-11-4"></a><span class="w"> </span><span class="nt">&quot;data&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;...&quot;</span><span class="p">],</span>
</span><span id="__span-11-5"><a id="__codelineno-11-5" name="__codelineno-11-5" href="#__codelineno-11-5"></a><span class="w"> </span><span class="nt">&quot;pagination&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-11-6"><a id="__codelineno-11-6" name="__codelineno-11-6" href="#__codelineno-11-6"></a><span class="w"> </span><span class="nt">&quot;total_count&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">100</span><span class="p">,</span>
</span><span id="__span-11-7"><a id="__codelineno-11-7" name="__codelineno-11-7" href="#__codelineno-11-7"></a><span class="w"> </span><span class="nt">&quot;pages&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">5</span><span class="p">,</span>
</span><span id="__span-11-8"><a id="__codelineno-11-8" name="__codelineno-11-8" href="#__codelineno-11-8"></a><span class="w"> </span><span class="nt">&quot;page&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span>
</span><span id="__span-11-9"><a id="__codelineno-11-9" name="__codelineno-11-9" href="#__codelineno-11-9"></a><span class="w"> </span><span class="nt">&quot;items_per_page&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">20</span><span class="p">,</span>
</span><span id="__span-11-10"><a id="__codelineno-11-10" name="__codelineno-11-10" href="#__codelineno-11-10"></a><span class="w"> </span><span class="nt">&quot;has_more&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span>
</span><span id="__span-11-11"><a id="__codelineno-11-11" name="__codelineno-11-11" href="#__codelineno-11-11"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-11-12"><a id="__codelineno-11-12" name="__codelineno-11-12" href="#__codelineno-11-12"></a><span class="p">}</span>
</span></code></pre></div>
<h4 id="skipping-the-count-query">Skipping the COUNT query<a class="headerlink" href="#skipping-the-count-query" title="Permanent link">&para;</a></h4>
<div class="admonition info">
<p class="admonition-title">Added in <code>v2.4.1</code></p>
</div>
<p>By default <code>offset_paginate</code> runs two queries: one for the page items and one <code>COUNT(*)</code> for <code>total_count</code>. On large tables the <code>COUNT</code> can be expensive. Pass <code>include_total=False</code> to <code>offset_paginate_params()</code> to skip it:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-11-1"><a id="__codelineno-11-1" name="__codelineno-11-1" href="#__codelineno-11-1"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
</span><span id="__span-11-2"><a id="__codelineno-11-2" name="__codelineno-11-2" href="#__codelineno-11-2"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">get_users</span><span class="p">(</span>
</span><span id="__span-11-3"><a id="__codelineno-11-3" name="__codelineno-11-3" href="#__codelineno-11-3"></a> <span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span>
</span><span id="__span-11-4"><a id="__codelineno-11-4" name="__codelineno-11-4" href="#__codelineno-11-4"></a> <span class="n">params</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">dict</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate_params</span><span class="p">(</span><span class="n">include_total</span><span class="o">=</span><span class="kc">False</span><span class="p">))],</span>
</span><span id="__span-11-5"><a id="__codelineno-11-5" name="__codelineno-11-5" href="#__codelineno-11-5"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">OffsetPaginatedResponse</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-11-6"><a id="__codelineno-11-6" name="__codelineno-11-6" href="#__codelineno-11-6"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">)</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-12-1"><a id="__codelineno-12-1" name="__codelineno-12-1" href="#__codelineno-12-1"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
</span><span id="__span-12-2"><a id="__codelineno-12-2" name="__codelineno-12-2" href="#__codelineno-12-2"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">get_users</span><span class="p">(</span>
</span><span id="__span-12-3"><a id="__codelineno-12-3" name="__codelineno-12-3" href="#__codelineno-12-3"></a> <span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span>
</span><span id="__span-12-4"><a id="__codelineno-12-4" name="__codelineno-12-4" href="#__codelineno-12-4"></a> <span class="n">params</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">dict</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate_params</span><span class="p">(</span><span class="n">include_total</span><span class="o">=</span><span class="kc">False</span><span class="p">))],</span>
</span><span id="__span-12-5"><a id="__codelineno-12-5" name="__codelineno-12-5" href="#__codelineno-12-5"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">OffsetPaginatedResponse</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-12-6"><a id="__codelineno-12-6" name="__codelineno-12-6" href="#__codelineno-12-6"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">)</span>
</span></code></pre></div>
<h3 id="cursor-pagination">Cursor pagination<a class="headerlink" href="#cursor-pagination" title="Permanent link">&para;</a></h3>
<div class="language-python highlight"><pre><span></span><code><span id="__span-12-1"><a id="__codelineno-12-1" name="__codelineno-12-1" href="#__codelineno-12-1"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
</span><span id="__span-12-2"><a id="__codelineno-12-2" name="__codelineno-12-2" href="#__codelineno-12-2"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">list_users</span><span class="p">(</span>
</span><span id="__span-12-3"><a id="__codelineno-12-3" name="__codelineno-12-3" href="#__codelineno-12-3"></a> <span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span>
</span><span id="__span-12-4"><a id="__codelineno-12-4" name="__codelineno-12-4" href="#__codelineno-12-4"></a> <span class="n">params</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">dict</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">cursor_paginate_params</span><span class="p">())],</span>
</span><span id="__span-12-5"><a id="__codelineno-12-5" name="__codelineno-12-5" href="#__codelineno-12-5"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">CursorPaginatedResponse</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-12-6"><a id="__codelineno-12-6" name="__codelineno-12-6" href="#__codelineno-12-6"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">cursor_paginate</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">)</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-13-1"><a id="__codelineno-13-1" name="__codelineno-13-1" href="#__codelineno-13-1"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
</span><span id="__span-13-2"><a id="__codelineno-13-2" name="__codelineno-13-2" href="#__codelineno-13-2"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">list_users</span><span class="p">(</span>
</span><span id="__span-13-3"><a id="__codelineno-13-3" name="__codelineno-13-3" href="#__codelineno-13-3"></a> <span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span>
</span><span id="__span-13-4"><a id="__codelineno-13-4" name="__codelineno-13-4" href="#__codelineno-13-4"></a> <span class="n">params</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">dict</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">cursor_paginate_params</span><span class="p">())],</span>
</span><span id="__span-13-5"><a id="__codelineno-13-5" name="__codelineno-13-5" href="#__codelineno-13-5"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">CursorPaginatedResponse</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-13-6"><a id="__codelineno-13-6" name="__codelineno-13-6" href="#__codelineno-13-6"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">cursor_paginate</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">)</span>
</span></code></pre></div>
<p>The <a href="../../reference/crud/#fastapi_toolsets.crud.factory.AsyncCrud.cursor_paginate"><code>cursor_paginate</code></a> method returns a <a href="../../reference/schemas/#fastapi_toolsets.schemas.CursorPaginatedResponse"><code>CursorPaginatedResponse</code></a>:</p>
<div class="language-json highlight"><pre><span></span><code><span id="__span-13-1"><a id="__codelineno-13-1" name="__codelineno-13-1" href="#__codelineno-13-1"></a><span class="p">{</span>
</span><span id="__span-13-2"><a id="__codelineno-13-2" name="__codelineno-13-2" href="#__codelineno-13-2"></a><span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;SUCCESS&quot;</span><span class="p">,</span>
</span><span id="__span-13-3"><a id="__codelineno-13-3" name="__codelineno-13-3" href="#__codelineno-13-3"></a><span class="w"> </span><span class="nt">&quot;pagination_type&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;cursor&quot;</span><span class="p">,</span>
</span><span id="__span-13-4"><a id="__codelineno-13-4" name="__codelineno-13-4" href="#__codelineno-13-4"></a><span class="w"> </span><span class="nt">&quot;data&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;...&quot;</span><span class="p">],</span>
</span><span id="__span-13-5"><a id="__codelineno-13-5" name="__codelineno-13-5" href="#__codelineno-13-5"></a><span class="w"> </span><span class="nt">&quot;pagination&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-13-6"><a id="__codelineno-13-6" name="__codelineno-13-6" href="#__codelineno-13-6"></a><span class="w"> </span><span class="nt">&quot;next_cursor&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;eyJ2YWx1ZSI6ICIzZjQ3YWM2OS0uLi4ifQ==&quot;</span><span class="p">,</span>
</span><span id="__span-13-7"><a id="__codelineno-13-7" name="__codelineno-13-7" href="#__codelineno-13-7"></a><span class="w"> </span><span class="nt">&quot;prev_cursor&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span>
</span><span id="__span-13-8"><a id="__codelineno-13-8" name="__codelineno-13-8" href="#__codelineno-13-8"></a><span class="w"> </span><span class="nt">&quot;items_per_page&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">20</span><span class="p">,</span>
</span><span id="__span-13-9"><a id="__codelineno-13-9" name="__codelineno-13-9" href="#__codelineno-13-9"></a><span class="w"> </span><span class="nt">&quot;has_more&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span>
</span><span id="__span-13-10"><a id="__codelineno-13-10" name="__codelineno-13-10" href="#__codelineno-13-10"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-13-11"><a id="__codelineno-13-11" name="__codelineno-13-11" href="#__codelineno-13-11"></a><span class="p">}</span>
<div class="language-json highlight"><pre><span></span><code><span id="__span-14-1"><a id="__codelineno-14-1" name="__codelineno-14-1" href="#__codelineno-14-1"></a><span class="p">{</span>
</span><span id="__span-14-2"><a id="__codelineno-14-2" name="__codelineno-14-2" href="#__codelineno-14-2"></a><span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;SUCCESS&quot;</span><span class="p">,</span>
</span><span id="__span-14-3"><a id="__codelineno-14-3" name="__codelineno-14-3" href="#__codelineno-14-3"></a><span class="w"> </span><span class="nt">&quot;pagination_type&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;cursor&quot;</span><span class="p">,</span>
</span><span id="__span-14-4"><a id="__codelineno-14-4" name="__codelineno-14-4" href="#__codelineno-14-4"></a><span class="w"> </span><span class="nt">&quot;data&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;...&quot;</span><span class="p">],</span>
</span><span id="__span-14-5"><a id="__codelineno-14-5" name="__codelineno-14-5" href="#__codelineno-14-5"></a><span class="w"> </span><span class="nt">&quot;pagination&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-14-6"><a id="__codelineno-14-6" name="__codelineno-14-6" href="#__codelineno-14-6"></a><span class="w"> </span><span class="nt">&quot;next_cursor&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;eyJ2YWx1ZSI6ICIzZjQ3YWM2OS0uLi4ifQ==&quot;</span><span class="p">,</span>
</span><span id="__span-14-7"><a id="__codelineno-14-7" name="__codelineno-14-7" href="#__codelineno-14-7"></a><span class="w"> </span><span class="nt">&quot;prev_cursor&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span>
</span><span id="__span-14-8"><a id="__codelineno-14-8" name="__codelineno-14-8" href="#__codelineno-14-8"></a><span class="w"> </span><span class="nt">&quot;items_per_page&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">20</span><span class="p">,</span>
</span><span id="__span-14-9"><a id="__codelineno-14-9" name="__codelineno-14-9" href="#__codelineno-14-9"></a><span class="w"> </span><span class="nt">&quot;has_more&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span>
</span><span id="__span-14-10"><a id="__codelineno-14-10" name="__codelineno-14-10" href="#__codelineno-14-10"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-14-11"><a id="__codelineno-14-11" name="__codelineno-14-11" href="#__codelineno-14-11"></a><span class="p">}</span>
</span></code></pre></div>
<p>Pass <code>next_cursor</code> as the <code>cursor</code> query parameter on the next request to advance to the next page. <code>prev_cursor</code> is set on pages 2+ and points back to the first item of the current page. Both are <code>null</code> when there is no adjacent page.</p>
<h4 id="choosing-a-cursor-column">Choosing a cursor column<a class="headerlink" href="#choosing-a-cursor-column" title="Permanent link">&para;</a></h4>
@@ -2459,28 +2636,28 @@
</tr>
</tbody>
</table>
<div class="language-python highlight"><pre><span></span><code><span id="__span-14-1"><a id="__codelineno-14-1" name="__codelineno-14-1" href="#__codelineno-14-1"></a><span class="c1"># Paginate by the primary key</span>
</span><span id="__span-14-2"><a id="__codelineno-14-2" name="__codelineno-14-2" href="#__codelineno-14-2"></a><span class="n">PostCrud</span> <span class="o">=</span> <span class="n">CrudFactory</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="n">Post</span><span class="p">,</span> <span class="n">cursor_column</span><span class="o">=</span><span class="n">Post</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
</span><span id="__span-14-3"><a id="__codelineno-14-3" name="__codelineno-14-3" href="#__codelineno-14-3"></a>
</span><span id="__span-14-4"><a id="__codelineno-14-4" name="__codelineno-14-4" href="#__codelineno-14-4"></a><span class="c1"># Paginate by a timestamp column instead</span>
</span><span id="__span-14-5"><a id="__codelineno-14-5" name="__codelineno-14-5" href="#__codelineno-14-5"></a><span class="n">PostCrud</span> <span class="o">=</span> <span class="n">CrudFactory</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="n">Post</span><span class="p">,</span> <span class="n">cursor_column</span><span class="o">=</span><span class="n">Post</span><span class="o">.</span><span class="n">created_at</span><span class="p">)</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-15-1"><a id="__codelineno-15-1" name="__codelineno-15-1" href="#__codelineno-15-1"></a><span class="c1"># Paginate by the primary key</span>
</span><span id="__span-15-2"><a id="__codelineno-15-2" name="__codelineno-15-2" href="#__codelineno-15-2"></a><span class="n">PostCrud</span> <span class="o">=</span> <span class="n">CrudFactory</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="n">Post</span><span class="p">,</span> <span class="n">cursor_column</span><span class="o">=</span><span class="n">Post</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
</span><span id="__span-15-3"><a id="__codelineno-15-3" name="__codelineno-15-3" href="#__codelineno-15-3"></a>
</span><span id="__span-15-4"><a id="__codelineno-15-4" name="__codelineno-15-4" href="#__codelineno-15-4"></a><span class="c1"># Paginate by a timestamp column instead</span>
</span><span id="__span-15-5"><a id="__codelineno-15-5" name="__codelineno-15-5" href="#__codelineno-15-5"></a><span class="n">PostCrud</span> <span class="o">=</span> <span class="n">CrudFactory</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="n">Post</span><span class="p">,</span> <span class="n">cursor_column</span><span class="o">=</span><span class="n">Post</span><span class="o">.</span><span class="n">created_at</span><span class="p">)</span>
</span></code></pre></div>
<h3 id="unified-endpoint-both-strategies">Unified endpoint (both strategies)<a class="headerlink" href="#unified-endpoint-both-strategies" title="Permanent link">&para;</a></h3>
<div class="admonition info">
<p class="admonition-title">Added in <code>v2.3.0</code></p>
</div>
<p><a href="../../reference/crud/#fastapi_toolsets.crud.factory.AsyncCrud.paginate"><code>paginate()</code></a> dispatches to <code>offset_paginate</code> or <code>cursor_paginate</code> based on a <code>pagination_type</code> query parameter, letting you expose <strong>one endpoint</strong> that supports both strategies. The <code>pagination_type</code> field in the response tells clients which strategy was used, enabling frontend discriminated-union typing.</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-15-1"><a id="__codelineno-15-1" name="__codelineno-15-1" href="#__codelineno-15-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.schemas</span><span class="w"> </span><span class="kn">import</span> <span class="n">PaginatedResponse</span>
</span><span id="__span-15-2"><a id="__codelineno-15-2" name="__codelineno-15-2" href="#__codelineno-15-2"></a>
</span><span id="__span-15-3"><a id="__codelineno-15-3" name="__codelineno-15-3" href="#__codelineno-15-3"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
</span><span id="__span-15-4"><a id="__codelineno-15-4" name="__codelineno-15-4" href="#__codelineno-15-4"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">list_users</span><span class="p">(</span>
</span><span id="__span-15-5"><a id="__codelineno-15-5" name="__codelineno-15-5" href="#__codelineno-15-5"></a> <span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span>
</span><span id="__span-15-6"><a id="__codelineno-15-6" name="__codelineno-15-6" href="#__codelineno-15-6"></a> <span class="n">params</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">dict</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">paginate_params</span><span class="p">())],</span>
</span><span id="__span-15-7"><a id="__codelineno-15-7" name="__codelineno-15-7" href="#__codelineno-15-7"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">PaginatedResponse</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-15-8"><a id="__codelineno-15-8" name="__codelineno-15-8" href="#__codelineno-15-8"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">paginate</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">)</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-16-1"><a id="__codelineno-16-1" name="__codelineno-16-1" href="#__codelineno-16-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.schemas</span><span class="w"> </span><span class="kn">import</span> <span class="n">PaginatedResponse</span>
</span><span id="__span-16-2"><a id="__codelineno-16-2" name="__codelineno-16-2" href="#__codelineno-16-2"></a>
</span><span id="__span-16-3"><a id="__codelineno-16-3" name="__codelineno-16-3" href="#__codelineno-16-3"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
</span><span id="__span-16-4"><a id="__codelineno-16-4" name="__codelineno-16-4" href="#__codelineno-16-4"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">list_users</span><span class="p">(</span>
</span><span id="__span-16-5"><a id="__codelineno-16-5" name="__codelineno-16-5" href="#__codelineno-16-5"></a> <span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span>
</span><span id="__span-16-6"><a id="__codelineno-16-6" name="__codelineno-16-6" href="#__codelineno-16-6"></a> <span class="n">params</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">dict</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">paginate_params</span><span class="p">())],</span>
</span><span id="__span-16-7"><a id="__codelineno-16-7" name="__codelineno-16-7" href="#__codelineno-16-7"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">PaginatedResponse</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-16-8"><a id="__codelineno-16-8" name="__codelineno-16-8" href="#__codelineno-16-8"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">paginate</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">)</span>
</span></code></pre></div>
<div class="language-text highlight"><pre><span></span><code><span id="__span-16-1"><a id="__codelineno-16-1" name="__codelineno-16-1" href="#__codelineno-16-1"></a>GET /users?pagination_type=offset&amp;page=2&amp;items_per_page=10
</span><span id="__span-16-2"><a id="__codelineno-16-2" name="__codelineno-16-2" href="#__codelineno-16-2"></a>GET /users?pagination_type=cursor&amp;cursor=eyJ2YWx1ZSI6...&amp;items_per_page=10
<div class="language-text highlight"><pre><span></span><code><span id="__span-17-1"><a id="__codelineno-17-1" name="__codelineno-17-1" href="#__codelineno-17-1"></a>GET /users?pagination_type=offset&amp;page=2&amp;items_per_page=10
</span><span id="__span-17-2"><a id="__codelineno-17-2" name="__codelineno-17-2" href="#__codelineno-17-2"></a>GET /users?pagination_type=cursor&amp;cursor=eyJ2YWx1ZSI6...&amp;items_per_page=10
</span></code></pre></div>
<h2 id="search">Search<a class="headerlink" href="#search" title="Permanent link">&para;</a></h2>
<p>Two search strategies are available, both compatible with <a href="../../reference/crud/#fastapi_toolsets.crud.factory.AsyncCrud.offset_paginate"><code>offset_paginate</code></a> and <a href="../../reference/crud/#fastapi_toolsets.crud.factory.AsyncCrud.cursor_paginate"><code>cursor_paginate</code></a>.</p>
@@ -2519,38 +2696,38 @@
<p>The model's primary key is always included in <code>searchable_fields</code> automatically, so searching by ID works out of the box without any configuration. When no <code>searchable_fields</code> are declared, only the primary key is searched.</p>
</div>
<p>Declare <code>searchable_fields</code> on the CRUD class. Relationship traversal is supported via tuples:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-17-1"><a id="__codelineno-17-1" name="__codelineno-17-1" href="#__codelineno-17-1"></a><span class="n">PostCrud</span> <span class="o">=</span> <span class="n">CrudFactory</span><span class="p">(</span>
</span><span id="__span-17-2"><a id="__codelineno-17-2" name="__codelineno-17-2" href="#__codelineno-17-2"></a> <span class="n">model</span><span class="o">=</span><span class="n">Post</span><span class="p">,</span>
</span><span id="__span-17-3"><a id="__codelineno-17-3" name="__codelineno-17-3" href="#__codelineno-17-3"></a> <span class="n">searchable_fields</span><span class="o">=</span><span class="p">[</span>
</span><span id="__span-17-4"><a id="__codelineno-17-4" name="__codelineno-17-4" href="#__codelineno-17-4"></a> <span class="n">Post</span><span class="o">.</span><span class="n">title</span><span class="p">,</span>
</span><span id="__span-17-5"><a id="__codelineno-17-5" name="__codelineno-17-5" href="#__codelineno-17-5"></a> <span class="n">Post</span><span class="o">.</span><span class="n">content</span><span class="p">,</span>
</span><span id="__span-17-6"><a id="__codelineno-17-6" name="__codelineno-17-6" href="#__codelineno-17-6"></a> <span class="p">(</span><span class="n">Post</span><span class="o">.</span><span class="n">author</span><span class="p">,</span> <span class="n">User</span><span class="o">.</span><span class="n">username</span><span class="p">),</span> <span class="c1"># search across relationship</span>
</span><span id="__span-17-7"><a id="__codelineno-17-7" name="__codelineno-17-7" href="#__codelineno-17-7"></a> <span class="p">],</span>
</span><span id="__span-17-8"><a id="__codelineno-17-8" name="__codelineno-17-8" href="#__codelineno-17-8"></a><span class="p">)</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-18-1"><a id="__codelineno-18-1" name="__codelineno-18-1" href="#__codelineno-18-1"></a><span class="n">PostCrud</span> <span class="o">=</span> <span class="n">CrudFactory</span><span class="p">(</span>
</span><span id="__span-18-2"><a id="__codelineno-18-2" name="__codelineno-18-2" href="#__codelineno-18-2"></a> <span class="n">model</span><span class="o">=</span><span class="n">Post</span><span class="p">,</span>
</span><span id="__span-18-3"><a id="__codelineno-18-3" name="__codelineno-18-3" href="#__codelineno-18-3"></a> <span class="n">searchable_fields</span><span class="o">=</span><span class="p">[</span>
</span><span id="__span-18-4"><a id="__codelineno-18-4" name="__codelineno-18-4" href="#__codelineno-18-4"></a> <span class="n">Post</span><span class="o">.</span><span class="n">title</span><span class="p">,</span>
</span><span id="__span-18-5"><a id="__codelineno-18-5" name="__codelineno-18-5" href="#__codelineno-18-5"></a> <span class="n">Post</span><span class="o">.</span><span class="n">content</span><span class="p">,</span>
</span><span id="__span-18-6"><a id="__codelineno-18-6" name="__codelineno-18-6" href="#__codelineno-18-6"></a> <span class="p">(</span><span class="n">Post</span><span class="o">.</span><span class="n">author</span><span class="p">,</span> <span class="n">User</span><span class="o">.</span><span class="n">username</span><span class="p">),</span> <span class="c1"># search across relationship</span>
</span><span id="__span-18-7"><a id="__codelineno-18-7" name="__codelineno-18-7" href="#__codelineno-18-7"></a> <span class="p">],</span>
</span><span id="__span-18-8"><a id="__codelineno-18-8" name="__codelineno-18-8" href="#__codelineno-18-8"></a><span class="p">)</span>
</span></code></pre></div>
<p>You can override <code>searchable_fields</code> per call with <code>search_fields</code>:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-18-1"><a id="__codelineno-18-1" name="__codelineno-18-1" href="#__codelineno-18-1"></a><span class="n">result</span> <span class="o">=</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate</span><span class="p">(</span>
</span><span id="__span-18-2"><a id="__codelineno-18-2" name="__codelineno-18-2" href="#__codelineno-18-2"></a> <span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span>
</span><span id="__span-18-3"><a id="__codelineno-18-3" name="__codelineno-18-3" href="#__codelineno-18-3"></a> <span class="n">search_fields</span><span class="o">=</span><span class="p">[</span><span class="n">User</span><span class="o">.</span><span class="n">country</span><span class="p">],</span>
</span><span id="__span-18-4"><a id="__codelineno-18-4" name="__codelineno-18-4" href="#__codelineno-18-4"></a><span class="p">)</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-19-1"><a id="__codelineno-19-1" name="__codelineno-19-1" href="#__codelineno-19-1"></a><span class="n">result</span> <span class="o">=</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate</span><span class="p">(</span>
</span><span id="__span-19-2"><a id="__codelineno-19-2" name="__codelineno-19-2" href="#__codelineno-19-2"></a> <span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span>
</span><span id="__span-19-3"><a id="__codelineno-19-3" name="__codelineno-19-3" href="#__codelineno-19-3"></a> <span class="n">search_fields</span><span class="o">=</span><span class="p">[</span><span class="n">User</span><span class="o">.</span><span class="n">country</span><span class="p">],</span>
</span><span id="__span-19-4"><a id="__codelineno-19-4" name="__codelineno-19-4" href="#__codelineno-19-4"></a><span class="p">)</span>
</span></code></pre></div>
<p>Or via the dependency to narrow which fields are exposed as query parameters:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-19-1"><a id="__codelineno-19-1" name="__codelineno-19-1" href="#__codelineno-19-1"></a><span class="n">params</span> <span class="o">=</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate_params</span><span class="p">(</span><span class="n">search_fields</span><span class="o">=</span><span class="p">[</span><span class="n">Post</span><span class="o">.</span><span class="n">title</span><span class="p">])</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-20-1"><a id="__codelineno-20-1" name="__codelineno-20-1" href="#__codelineno-20-1"></a><span class="n">params</span> <span class="o">=</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate_params</span><span class="p">(</span><span class="n">search_fields</span><span class="o">=</span><span class="p">[</span><span class="n">Post</span><span class="o">.</span><span class="n">title</span><span class="p">])</span>
</span></code></pre></div>
<p>This allows searching with both <a href="../../reference/crud/#fastapi_toolsets.crud.factory.AsyncCrud.offset_paginate"><code>offset_paginate</code></a> and <a href="../../reference/crud/#fastapi_toolsets.crud.factory.AsyncCrud.cursor_paginate"><code>cursor_paginate</code></a>:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-20-1"><a id="__codelineno-20-1" name="__codelineno-20-1" href="#__codelineno-20-1"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
</span><span id="__span-20-2"><a id="__codelineno-20-2" name="__codelineno-20-2" href="#__codelineno-20-2"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">get_users</span><span class="p">(</span>
</span><span id="__span-20-3"><a id="__codelineno-20-3" name="__codelineno-20-3" href="#__codelineno-20-3"></a> <span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span>
</span><span id="__span-20-4"><a id="__codelineno-20-4" name="__codelineno-20-4" href="#__codelineno-20-4"></a> <span class="n">params</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">dict</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate_params</span><span class="p">())],</span>
</span><span id="__span-20-5"><a id="__codelineno-20-5" name="__codelineno-20-5" href="#__codelineno-20-5"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">OffsetPaginatedResponse</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-20-6"><a id="__codelineno-20-6" name="__codelineno-20-6" href="#__codelineno-20-6"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">)</span>
</span></code></pre></div>
<div class="language-python highlight"><pre><span></span><code><span id="__span-21-1"><a id="__codelineno-21-1" name="__codelineno-21-1" href="#__codelineno-21-1"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
</span><span id="__span-21-2"><a id="__codelineno-21-2" name="__codelineno-21-2" href="#__codelineno-21-2"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">get_users</span><span class="p">(</span>
</span><span id="__span-21-3"><a id="__codelineno-21-3" name="__codelineno-21-3" href="#__codelineno-21-3"></a> <span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span>
</span><span id="__span-21-4"><a id="__codelineno-21-4" name="__codelineno-21-4" href="#__codelineno-21-4"></a> <span class="n">params</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">dict</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">cursor_paginate_params</span><span class="p">())],</span>
</span><span id="__span-21-5"><a id="__codelineno-21-5" name="__codelineno-21-5" href="#__codelineno-21-5"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">CursorPaginatedResponse</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-21-6"><a id="__codelineno-21-6" name="__codelineno-21-6" href="#__codelineno-21-6"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">cursor_paginate</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">)</span>
</span><span id="__span-21-4"><a id="__codelineno-21-4" name="__codelineno-21-4" href="#__codelineno-21-4"></a> <span class="n">params</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">dict</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate_params</span><span class="p">())],</span>
</span><span id="__span-21-5"><a id="__codelineno-21-5" name="__codelineno-21-5" href="#__codelineno-21-5"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">OffsetPaginatedResponse</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-21-6"><a id="__codelineno-21-6" name="__codelineno-21-6" href="#__codelineno-21-6"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">)</span>
</span></code></pre></div>
<div class="language-python highlight"><pre><span></span><code><span id="__span-22-1"><a id="__codelineno-22-1" name="__codelineno-22-1" href="#__codelineno-22-1"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
</span><span id="__span-22-2"><a id="__codelineno-22-2" name="__codelineno-22-2" href="#__codelineno-22-2"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">get_users</span><span class="p">(</span>
</span><span id="__span-22-3"><a id="__codelineno-22-3" name="__codelineno-22-3" href="#__codelineno-22-3"></a> <span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span>
</span><span id="__span-22-4"><a id="__codelineno-22-4" name="__codelineno-22-4" href="#__codelineno-22-4"></a> <span class="n">params</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">dict</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">cursor_paginate_params</span><span class="p">())],</span>
</span><span id="__span-22-5"><a id="__codelineno-22-5" name="__codelineno-22-5" href="#__codelineno-22-5"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">CursorPaginatedResponse</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-22-6"><a id="__codelineno-22-6" name="__codelineno-22-6" href="#__codelineno-22-6"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">cursor_paginate</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">)</span>
</span></code></pre></div>
<p>The dependency adds two query parameters to the endpoint:</p>
<table>
@@ -2571,16 +2748,16 @@
</tr>
</tbody>
</table>
<div class="language-text highlight"><pre><span></span><code><span id="__span-22-1"><a id="__codelineno-22-1" name="__codelineno-22-1" href="#__codelineno-22-1"></a>GET /posts?search=hello → search all configured columns
</span><span id="__span-22-2"><a id="__codelineno-22-2" name="__codelineno-22-2" href="#__codelineno-22-2"></a>GET /posts?search=hello&amp;search_column=title → search only Post.title
<div class="language-text highlight"><pre><span></span><code><span id="__span-23-1"><a id="__codelineno-23-1" name="__codelineno-23-1" href="#__codelineno-23-1"></a>GET /posts?search=hello → search all configured columns
</span><span id="__span-23-2"><a id="__codelineno-23-2" name="__codelineno-23-2" href="#__codelineno-23-2"></a>GET /posts?search=hello&amp;search_column=title → search only Post.title
</span></code></pre></div>
<p>The available search column keys are returned in the <code>search_columns</code> field of <a href="../../reference/schemas/#fastapi_toolsets.schemas.PaginatedResponse"><code>PaginatedResponse</code></a>. Use them to populate a column picker in the UI, or to validate <code>search_column</code> values on the client side:</p>
<div class="language-json highlight"><pre><span></span><code><span id="__span-23-1"><a id="__codelineno-23-1" name="__codelineno-23-1" href="#__codelineno-23-1"></a><span class="p">{</span>
</span><span id="__span-23-2"><a id="__codelineno-23-2" name="__codelineno-23-2" href="#__codelineno-23-2"></a><span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;SUCCESS&quot;</span><span class="p">,</span>
</span><span id="__span-23-3"><a id="__codelineno-23-3" name="__codelineno-23-3" href="#__codelineno-23-3"></a><span class="w"> </span><span class="nt">&quot;data&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;...&quot;</span><span class="p">],</span>
</span><span id="__span-23-4"><a id="__codelineno-23-4" name="__codelineno-23-4" href="#__codelineno-23-4"></a><span class="w"> </span><span class="nt">&quot;pagination&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="s2">&quot;...&quot;</span><span class="w"> </span><span class="p">},</span>
</span><span id="__span-23-5"><a id="__codelineno-23-5" name="__codelineno-23-5" href="#__codelineno-23-5"></a><span class="w"> </span><span class="nt">&quot;search_columns&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;content&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;author__username&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;title&quot;</span><span class="p">]</span>
</span><span id="__span-23-6"><a id="__codelineno-23-6" name="__codelineno-23-6" href="#__codelineno-23-6"></a><span class="p">}</span>
<div class="language-json highlight"><pre><span></span><code><span id="__span-24-1"><a id="__codelineno-24-1" name="__codelineno-24-1" href="#__codelineno-24-1"></a><span class="p">{</span>
</span><span id="__span-24-2"><a id="__codelineno-24-2" name="__codelineno-24-2" href="#__codelineno-24-2"></a><span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;SUCCESS&quot;</span><span class="p">,</span>
</span><span id="__span-24-3"><a id="__codelineno-24-3" name="__codelineno-24-3" href="#__codelineno-24-3"></a><span class="w"> </span><span class="nt">&quot;data&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;...&quot;</span><span class="p">],</span>
</span><span id="__span-24-4"><a id="__codelineno-24-4" name="__codelineno-24-4" href="#__codelineno-24-4"></a><span class="w"> </span><span class="nt">&quot;pagination&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="s2">&quot;...&quot;</span><span class="w"> </span><span class="p">},</span>
</span><span id="__span-24-5"><a id="__codelineno-24-5" name="__codelineno-24-5" href="#__codelineno-24-5"></a><span class="w"> </span><span class="nt">&quot;search_columns&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;content&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;author__username&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;title&quot;</span><span class="p">]</span>
</span><span id="__span-24-6"><a id="__codelineno-24-6" name="__codelineno-24-6" href="#__codelineno-24-6"></a><span class="p">}</span>
</span></code></pre></div>
<div class="admonition info">
<p class="admonition-title">Key format uses <code>__</code> as a separator for relationship chains.</p>
@@ -2591,60 +2768,60 @@
<p class="admonition-title">Added in <code>v1.2</code></p>
</div>
<p>Declare <code>facet_fields</code> on the CRUD class to return distinct column values alongside paginated results. This is useful for populating filter dropdowns or building faceted search UIs. Relationship traversal is supported via tuples, using the same syntax as <code>searchable_fields</code>:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-24-1"><a id="__codelineno-24-1" name="__codelineno-24-1" href="#__codelineno-24-1"></a><span class="n">UserCrud</span> <span class="o">=</span> <span class="n">CrudFactory</span><span class="p">(</span>
</span><span id="__span-24-2"><a id="__codelineno-24-2" name="__codelineno-24-2" href="#__codelineno-24-2"></a> <span class="n">model</span><span class="o">=</span><span class="n">User</span><span class="p">,</span>
</span><span id="__span-24-3"><a id="__codelineno-24-3" name="__codelineno-24-3" href="#__codelineno-24-3"></a> <span class="n">facet_fields</span><span class="o">=</span><span class="p">[</span>
</span><span id="__span-24-4"><a id="__codelineno-24-4" name="__codelineno-24-4" href="#__codelineno-24-4"></a> <span class="n">User</span><span class="o">.</span><span class="n">status</span><span class="p">,</span>
</span><span id="__span-24-5"><a id="__codelineno-24-5" name="__codelineno-24-5" href="#__codelineno-24-5"></a> <span class="n">User</span><span class="o">.</span><span class="n">country</span><span class="p">,</span>
</span><span id="__span-24-6"><a id="__codelineno-24-6" name="__codelineno-24-6" href="#__codelineno-24-6"></a> <span class="p">(</span><span class="n">User</span><span class="o">.</span><span class="n">role</span><span class="p">,</span> <span class="n">Role</span><span class="o">.</span><span class="n">name</span><span class="p">),</span> <span class="c1"># value from a related model</span>
</span><span id="__span-24-7"><a id="__codelineno-24-7" name="__codelineno-24-7" href="#__codelineno-24-7"></a> <span class="p">],</span>
</span><span id="__span-24-8"><a id="__codelineno-24-8" name="__codelineno-24-8" href="#__codelineno-24-8"></a><span class="p">)</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-25-1"><a id="__codelineno-25-1" name="__codelineno-25-1" href="#__codelineno-25-1"></a><span class="n">UserCrud</span> <span class="o">=</span> <span class="n">CrudFactory</span><span class="p">(</span>
</span><span id="__span-25-2"><a id="__codelineno-25-2" name="__codelineno-25-2" href="#__codelineno-25-2"></a> <span class="n">model</span><span class="o">=</span><span class="n">User</span><span class="p">,</span>
</span><span id="__span-25-3"><a id="__codelineno-25-3" name="__codelineno-25-3" href="#__codelineno-25-3"></a> <span class="n">facet_fields</span><span class="o">=</span><span class="p">[</span>
</span><span id="__span-25-4"><a id="__codelineno-25-4" name="__codelineno-25-4" href="#__codelineno-25-4"></a> <span class="n">User</span><span class="o">.</span><span class="n">status</span><span class="p">,</span>
</span><span id="__span-25-5"><a id="__codelineno-25-5" name="__codelineno-25-5" href="#__codelineno-25-5"></a> <span class="n">User</span><span class="o">.</span><span class="n">country</span><span class="p">,</span>
</span><span id="__span-25-6"><a id="__codelineno-25-6" name="__codelineno-25-6" href="#__codelineno-25-6"></a> <span class="p">(</span><span class="n">User</span><span class="o">.</span><span class="n">role</span><span class="p">,</span> <span class="n">Role</span><span class="o">.</span><span class="n">name</span><span class="p">),</span> <span class="c1"># value from a related model</span>
</span><span id="__span-25-7"><a id="__codelineno-25-7" name="__codelineno-25-7" href="#__codelineno-25-7"></a> <span class="p">],</span>
</span><span id="__span-25-8"><a id="__codelineno-25-8" name="__codelineno-25-8" href="#__codelineno-25-8"></a><span class="p">)</span>
</span></code></pre></div>
<p>You can override <code>facet_fields</code> per call:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-25-1"><a id="__codelineno-25-1" name="__codelineno-25-1" href="#__codelineno-25-1"></a><span class="n">result</span> <span class="o">=</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate</span><span class="p">(</span>
</span><span id="__span-25-2"><a id="__codelineno-25-2" name="__codelineno-25-2" href="#__codelineno-25-2"></a> <span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span>
</span><span id="__span-25-3"><a id="__codelineno-25-3" name="__codelineno-25-3" href="#__codelineno-25-3"></a> <span class="n">facet_fields</span><span class="o">=</span><span class="p">[</span><span class="n">User</span><span class="o">.</span><span class="n">country</span><span class="p">],</span>
</span><span id="__span-25-4"><a id="__codelineno-25-4" name="__codelineno-25-4" href="#__codelineno-25-4"></a><span class="p">)</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-26-1"><a id="__codelineno-26-1" name="__codelineno-26-1" href="#__codelineno-26-1"></a><span class="n">result</span> <span class="o">=</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate</span><span class="p">(</span>
</span><span id="__span-26-2"><a id="__codelineno-26-2" name="__codelineno-26-2" href="#__codelineno-26-2"></a> <span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span>
</span><span id="__span-26-3"><a id="__codelineno-26-3" name="__codelineno-26-3" href="#__codelineno-26-3"></a> <span class="n">facet_fields</span><span class="o">=</span><span class="p">[</span><span class="n">User</span><span class="o">.</span><span class="n">country</span><span class="p">],</span>
</span><span id="__span-26-4"><a id="__codelineno-26-4" name="__codelineno-26-4" href="#__codelineno-26-4"></a><span class="p">)</span>
</span></code></pre></div>
<p>Or via the dependency to narrow which fields are exposed as query parameters:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-26-1"><a id="__codelineno-26-1" name="__codelineno-26-1" href="#__codelineno-26-1"></a><span class="n">params</span> <span class="o">=</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate_params</span><span class="p">(</span><span class="n">facet_fields</span><span class="o">=</span><span class="p">[</span><span class="n">User</span><span class="o">.</span><span class="n">country</span><span class="p">])</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-27-1"><a id="__codelineno-27-1" name="__codelineno-27-1" href="#__codelineno-27-1"></a><span class="n">params</span> <span class="o">=</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate_params</span><span class="p">(</span><span class="n">facet_fields</span><span class="o">=</span><span class="p">[</span><span class="n">User</span><span class="o">.</span><span class="n">country</span><span class="p">])</span>
</span></code></pre></div>
<p>Facet filtering is built into the consolidated params dependencies. When <code>filter=True</code> (the default), each facet field is exposed as a query parameter and values are collected into <code>filter_by</code> automatically:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-27-1"><a id="__codelineno-27-1" name="__codelineno-27-1" href="#__codelineno-27-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Annotated</span>
</span><span id="__span-27-2"><a id="__codelineno-27-2" name="__codelineno-27-2" href="#__codelineno-27-2"></a>
</span><span id="__span-27-3"><a id="__codelineno-27-3" name="__codelineno-27-3" href="#__codelineno-27-3"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi</span><span class="w"> </span><span class="kn">import</span> <span class="n">Depends</span>
</span><span id="__span-27-4"><a id="__codelineno-27-4" name="__codelineno-27-4" href="#__codelineno-27-4"></a>
</span><span id="__span-27-5"><a id="__codelineno-27-5" name="__codelineno-27-5" href="#__codelineno-27-5"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="n">response_model_exclude_none</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="__span-27-6"><a id="__codelineno-27-6" name="__codelineno-27-6" href="#__codelineno-27-6"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">list_users</span><span class="p">(</span>
</span><span id="__span-27-7"><a id="__codelineno-27-7" name="__codelineno-27-7" href="#__codelineno-27-7"></a> <span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span>
</span><span id="__span-27-8"><a id="__codelineno-27-8" name="__codelineno-27-8" href="#__codelineno-27-8"></a> <span class="n">params</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">dict</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate_params</span><span class="p">())],</span>
</span><span id="__span-27-9"><a id="__codelineno-27-9" name="__codelineno-27-9" href="#__codelineno-27-9"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">OffsetPaginatedResponse</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-27-10"><a id="__codelineno-27-10" name="__codelineno-27-10" href="#__codelineno-27-10"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">)</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-28-1"><a id="__codelineno-28-1" name="__codelineno-28-1" href="#__codelineno-28-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Annotated</span>
</span><span id="__span-28-2"><a id="__codelineno-28-2" name="__codelineno-28-2" href="#__codelineno-28-2"></a>
</span><span id="__span-28-3"><a id="__codelineno-28-3" name="__codelineno-28-3" href="#__codelineno-28-3"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi</span><span class="w"> </span><span class="kn">import</span> <span class="n">Depends</span>
</span><span id="__span-28-4"><a id="__codelineno-28-4" name="__codelineno-28-4" href="#__codelineno-28-4"></a>
</span><span id="__span-28-5"><a id="__codelineno-28-5" name="__codelineno-28-5" href="#__codelineno-28-5"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="n">response_model_exclude_none</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="__span-28-6"><a id="__codelineno-28-6" name="__codelineno-28-6" href="#__codelineno-28-6"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">list_users</span><span class="p">(</span>
</span><span id="__span-28-7"><a id="__codelineno-28-7" name="__codelineno-28-7" href="#__codelineno-28-7"></a> <span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span>
</span><span id="__span-28-8"><a id="__codelineno-28-8" name="__codelineno-28-8" href="#__codelineno-28-8"></a> <span class="n">params</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">dict</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate_params</span><span class="p">())],</span>
</span><span id="__span-28-9"><a id="__codelineno-28-9" name="__codelineno-28-9" href="#__codelineno-28-9"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">OffsetPaginatedResponse</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-28-10"><a id="__codelineno-28-10" name="__codelineno-28-10" href="#__codelineno-28-10"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">)</span>
</span></code></pre></div>
<div class="language-python highlight"><pre><span></span><code><span id="__span-28-1"><a id="__codelineno-28-1" name="__codelineno-28-1" href="#__codelineno-28-1"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="n">response_model_exclude_none</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="__span-28-2"><a id="__codelineno-28-2" name="__codelineno-28-2" href="#__codelineno-28-2"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">list_users</span><span class="p">(</span>
</span><span id="__span-28-3"><a id="__codelineno-28-3" name="__codelineno-28-3" href="#__codelineno-28-3"></a> <span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span>
</span><span id="__span-28-4"><a id="__codelineno-28-4" name="__codelineno-28-4" href="#__codelineno-28-4"></a> <span class="n">params</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">dict</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">cursor_paginate_params</span><span class="p">())],</span>
</span><span id="__span-28-5"><a id="__codelineno-28-5" name="__codelineno-28-5" href="#__codelineno-28-5"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">CursorPaginatedResponse</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-28-6"><a id="__codelineno-28-6" name="__codelineno-28-6" href="#__codelineno-28-6"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">cursor_paginate</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">)</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-29-1"><a id="__codelineno-29-1" name="__codelineno-29-1" href="#__codelineno-29-1"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="n">response_model_exclude_none</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="__span-29-2"><a id="__codelineno-29-2" name="__codelineno-29-2" href="#__codelineno-29-2"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">list_users</span><span class="p">(</span>
</span><span id="__span-29-3"><a id="__codelineno-29-3" name="__codelineno-29-3" href="#__codelineno-29-3"></a> <span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span>
</span><span id="__span-29-4"><a id="__codelineno-29-4" name="__codelineno-29-4" href="#__codelineno-29-4"></a> <span class="n">params</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">dict</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">cursor_paginate_params</span><span class="p">())],</span>
</span><span id="__span-29-5"><a id="__codelineno-29-5" name="__codelineno-29-5" href="#__codelineno-29-5"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">CursorPaginatedResponse</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-29-6"><a id="__codelineno-29-6" name="__codelineno-29-6" href="#__codelineno-29-6"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">cursor_paginate</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">)</span>
</span></code></pre></div>
<p>Both single-value and multi-value query parameters work:</p>
<div class="language-text highlight"><pre><span></span><code><span id="__span-29-1"><a id="__codelineno-29-1" name="__codelineno-29-1" href="#__codelineno-29-1"></a>GET /users?status=active → filter_by={&quot;status&quot;: [&quot;active&quot;]}
</span><span id="__span-29-2"><a id="__codelineno-29-2" name="__codelineno-29-2" href="#__codelineno-29-2"></a>GET /users?status=active&amp;country=FR → filter_by={&quot;status&quot;: [&quot;active&quot;], &quot;country&quot;: [&quot;FR&quot;]}
</span><span id="__span-29-3"><a id="__codelineno-29-3" name="__codelineno-29-3" href="#__codelineno-29-3"></a>GET /users?role__name=admin&amp;role__name=editor → filter_by={&quot;role__name&quot;: [&quot;admin&quot;, &quot;editor&quot;]} (IN clause)
<div class="language-text highlight"><pre><span></span><code><span id="__span-30-1"><a id="__codelineno-30-1" name="__codelineno-30-1" href="#__codelineno-30-1"></a>GET /users?status=active → filter_by={&quot;status&quot;: [&quot;active&quot;]}
</span><span id="__span-30-2"><a id="__codelineno-30-2" name="__codelineno-30-2" href="#__codelineno-30-2"></a>GET /users?status=active&amp;country=FR → filter_by={&quot;status&quot;: [&quot;active&quot;], &quot;country&quot;: [&quot;FR&quot;]}
</span><span id="__span-30-3"><a id="__codelineno-30-3" name="__codelineno-30-3" href="#__codelineno-30-3"></a>GET /users?role__name=admin&amp;role__name=editor → filter_by={&quot;role__name&quot;: [&quot;admin&quot;, &quot;editor&quot;]} (IN clause)
</span></code></pre></div>
<p><code>filter_by</code> and <code>filters</code> can be combined — both are applied with AND logic.</p>
<p>The distinct values for each facet field are returned in the <code>filter_attributes</code> field of <a href="../../reference/schemas/#fastapi_toolsets.schemas.PaginatedResponse"><code>PaginatedResponse</code></a>. Use them to populate filter dropdowns in the UI, or to validate <code>filter_by</code> keys on the client side:</p>
<div class="language-json highlight"><pre><span></span><code><span id="__span-30-1"><a id="__codelineno-30-1" name="__codelineno-30-1" href="#__codelineno-30-1"></a><span class="p">{</span>
</span><span id="__span-30-2"><a id="__codelineno-30-2" name="__codelineno-30-2" href="#__codelineno-30-2"></a><span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;SUCCESS&quot;</span><span class="p">,</span>
</span><span id="__span-30-3"><a id="__codelineno-30-3" name="__codelineno-30-3" href="#__codelineno-30-3"></a><span class="w"> </span><span class="nt">&quot;data&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;...&quot;</span><span class="p">],</span>
</span><span id="__span-30-4"><a id="__codelineno-30-4" name="__codelineno-30-4" href="#__codelineno-30-4"></a><span class="w"> </span><span class="nt">&quot;pagination&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="s2">&quot;...&quot;</span><span class="w"> </span><span class="p">},</span>
</span><span id="__span-30-5"><a id="__codelineno-30-5" name="__codelineno-30-5" href="#__codelineno-30-5"></a><span class="w"> </span><span class="nt">&quot;filter_attributes&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-30-6"><a id="__codelineno-30-6" name="__codelineno-30-6" href="#__codelineno-30-6"></a><span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;active&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;inactive&quot;</span><span class="p">],</span>
</span><span id="__span-30-7"><a id="__codelineno-30-7" name="__codelineno-30-7" href="#__codelineno-30-7"></a><span class="w"> </span><span class="nt">&quot;country&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;DE&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;FR&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;US&quot;</span><span class="p">],</span>
</span><span id="__span-30-8"><a id="__codelineno-30-8" name="__codelineno-30-8" href="#__codelineno-30-8"></a><span class="w"> </span><span class="nt">&quot;role__name&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;admin&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;editor&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;viewer&quot;</span><span class="p">]</span>
</span><span id="__span-30-9"><a id="__codelineno-30-9" name="__codelineno-30-9" href="#__codelineno-30-9"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-30-10"><a id="__codelineno-30-10" name="__codelineno-30-10" href="#__codelineno-30-10"></a><span class="p">}</span>
<div class="language-json highlight"><pre><span></span><code><span id="__span-31-1"><a id="__codelineno-31-1" name="__codelineno-31-1" href="#__codelineno-31-1"></a><span class="p">{</span>
</span><span id="__span-31-2"><a id="__codelineno-31-2" name="__codelineno-31-2" href="#__codelineno-31-2"></a><span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;SUCCESS&quot;</span><span class="p">,</span>
</span><span id="__span-31-3"><a id="__codelineno-31-3" name="__codelineno-31-3" href="#__codelineno-31-3"></a><span class="w"> </span><span class="nt">&quot;data&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;...&quot;</span><span class="p">],</span>
</span><span id="__span-31-4"><a id="__codelineno-31-4" name="__codelineno-31-4" href="#__codelineno-31-4"></a><span class="w"> </span><span class="nt">&quot;pagination&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="s2">&quot;...&quot;</span><span class="w"> </span><span class="p">},</span>
</span><span id="__span-31-5"><a id="__codelineno-31-5" name="__codelineno-31-5" href="#__codelineno-31-5"></a><span class="w"> </span><span class="nt">&quot;filter_attributes&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-31-6"><a id="__codelineno-31-6" name="__codelineno-31-6" href="#__codelineno-31-6"></a><span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;active&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;inactive&quot;</span><span class="p">],</span>
</span><span id="__span-31-7"><a id="__codelineno-31-7" name="__codelineno-31-7" href="#__codelineno-31-7"></a><span class="w"> </span><span class="nt">&quot;country&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;DE&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;FR&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;US&quot;</span><span class="p">],</span>
</span><span id="__span-31-8"><a id="__codelineno-31-8" name="__codelineno-31-8" href="#__codelineno-31-8"></a><span class="w"> </span><span class="nt">&quot;role__name&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;admin&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;editor&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;viewer&quot;</span><span class="p">]</span>
</span><span id="__span-31-9"><a id="__codelineno-31-9" name="__codelineno-31-9" href="#__codelineno-31-9"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-31-10"><a id="__codelineno-31-10" name="__codelineno-31-10" href="#__codelineno-31-10"></a><span class="p">}</span>
</span></code></pre></div>
<div class="admonition info">
<p class="admonition-title">Key format uses <code>__</code> as a separator for relationship chains.</p>
@@ -2655,42 +2832,42 @@
<p class="admonition-title">Added in <code>v1.3</code></p>
</div>
<p>Declare <code>order_fields</code> on the CRUD class. Relationship traversal is supported via tuples, using the same syntax as <code>searchable_fields</code> and <code>facet_fields</code>:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-31-1"><a id="__codelineno-31-1" name="__codelineno-31-1" href="#__codelineno-31-1"></a><span class="n">UserCrud</span> <span class="o">=</span> <span class="n">CrudFactory</span><span class="p">(</span>
</span><span id="__span-31-2"><a id="__codelineno-31-2" name="__codelineno-31-2" href="#__codelineno-31-2"></a> <span class="n">model</span><span class="o">=</span><span class="n">User</span><span class="p">,</span>
</span><span id="__span-31-3"><a id="__codelineno-31-3" name="__codelineno-31-3" href="#__codelineno-31-3"></a> <span class="n">order_fields</span><span class="o">=</span><span class="p">[</span>
</span><span id="__span-31-4"><a id="__codelineno-31-4" name="__codelineno-31-4" href="#__codelineno-31-4"></a> <span class="n">User</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
</span><span id="__span-31-5"><a id="__codelineno-31-5" name="__codelineno-31-5" href="#__codelineno-31-5"></a> <span class="n">User</span><span class="o">.</span><span class="n">created_at</span><span class="p">,</span>
</span><span id="__span-31-6"><a id="__codelineno-31-6" name="__codelineno-31-6" href="#__codelineno-31-6"></a> <span class="p">(</span><span class="n">User</span><span class="o">.</span><span class="n">role</span><span class="p">,</span> <span class="n">Role</span><span class="o">.</span><span class="n">name</span><span class="p">),</span> <span class="c1"># sort by a related model column</span>
</span><span id="__span-31-7"><a id="__codelineno-31-7" name="__codelineno-31-7" href="#__codelineno-31-7"></a> <span class="p">],</span>
</span><span id="__span-31-8"><a id="__codelineno-31-8" name="__codelineno-31-8" href="#__codelineno-31-8"></a><span class="p">)</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-32-1"><a id="__codelineno-32-1" name="__codelineno-32-1" href="#__codelineno-32-1"></a><span class="n">UserCrud</span> <span class="o">=</span> <span class="n">CrudFactory</span><span class="p">(</span>
</span><span id="__span-32-2"><a id="__codelineno-32-2" name="__codelineno-32-2" href="#__codelineno-32-2"></a> <span class="n">model</span><span class="o">=</span><span class="n">User</span><span class="p">,</span>
</span><span id="__span-32-3"><a id="__codelineno-32-3" name="__codelineno-32-3" href="#__codelineno-32-3"></a> <span class="n">order_fields</span><span class="o">=</span><span class="p">[</span>
</span><span id="__span-32-4"><a id="__codelineno-32-4" name="__codelineno-32-4" href="#__codelineno-32-4"></a> <span class="n">User</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
</span><span id="__span-32-5"><a id="__codelineno-32-5" name="__codelineno-32-5" href="#__codelineno-32-5"></a> <span class="n">User</span><span class="o">.</span><span class="n">created_at</span><span class="p">,</span>
</span><span id="__span-32-6"><a id="__codelineno-32-6" name="__codelineno-32-6" href="#__codelineno-32-6"></a> <span class="p">(</span><span class="n">User</span><span class="o">.</span><span class="n">role</span><span class="p">,</span> <span class="n">Role</span><span class="o">.</span><span class="n">name</span><span class="p">),</span> <span class="c1"># sort by a related model column</span>
</span><span id="__span-32-7"><a id="__codelineno-32-7" name="__codelineno-32-7" href="#__codelineno-32-7"></a> <span class="p">],</span>
</span><span id="__span-32-8"><a id="__codelineno-32-8" name="__codelineno-32-8" href="#__codelineno-32-8"></a><span class="p">)</span>
</span></code></pre></div>
<p>You can override <code>order_fields</code> per call:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-32-1"><a id="__codelineno-32-1" name="__codelineno-32-1" href="#__codelineno-32-1"></a><span class="n">result</span> <span class="o">=</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate</span><span class="p">(</span>
</span><span id="__span-32-2"><a id="__codelineno-32-2" name="__codelineno-32-2" href="#__codelineno-32-2"></a> <span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span>
</span><span id="__span-32-3"><a id="__codelineno-32-3" name="__codelineno-32-3" href="#__codelineno-32-3"></a> <span class="n">order_fields</span><span class="o">=</span><span class="p">[</span><span class="n">User</span><span class="o">.</span><span class="n">name</span><span class="p">],</span>
</span><span id="__span-32-4"><a id="__codelineno-32-4" name="__codelineno-32-4" href="#__codelineno-32-4"></a><span class="p">)</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-33-1"><a id="__codelineno-33-1" name="__codelineno-33-1" href="#__codelineno-33-1"></a><span class="n">result</span> <span class="o">=</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate</span><span class="p">(</span>
</span><span id="__span-33-2"><a id="__codelineno-33-2" name="__codelineno-33-2" href="#__codelineno-33-2"></a> <span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span>
</span><span id="__span-33-3"><a id="__codelineno-33-3" name="__codelineno-33-3" href="#__codelineno-33-3"></a> <span class="n">order_fields</span><span class="o">=</span><span class="p">[</span><span class="n">User</span><span class="o">.</span><span class="n">name</span><span class="p">],</span>
</span><span id="__span-33-4"><a id="__codelineno-33-4" name="__codelineno-33-4" href="#__codelineno-33-4"></a><span class="p">)</span>
</span></code></pre></div>
<p>Or via the dependency to narrow which fields are exposed as query parameters:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-33-1"><a id="__codelineno-33-1" name="__codelineno-33-1" href="#__codelineno-33-1"></a><span class="n">params</span> <span class="o">=</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate_params</span><span class="p">(</span><span class="n">order_fields</span><span class="o">=</span><span class="p">[</span><span class="n">User</span><span class="o">.</span><span class="n">name</span><span class="p">])</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-34-1"><a id="__codelineno-34-1" name="__codelineno-34-1" href="#__codelineno-34-1"></a><span class="n">params</span> <span class="o">=</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate_params</span><span class="p">(</span><span class="n">order_fields</span><span class="o">=</span><span class="p">[</span><span class="n">User</span><span class="o">.</span><span class="n">name</span><span class="p">])</span>
</span></code></pre></div>
<p>Sorting is built into the consolidated params dependencies. When <code>order=True</code> (the default), <code>order_by</code> and <code>order</code> query parameters are exposed and resolved into an <code>OrderByClause</code> automatically:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-34-1"><a id="__codelineno-34-1" name="__codelineno-34-1" href="#__codelineno-34-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Annotated</span>
</span><span id="__span-34-2"><a id="__codelineno-34-2" name="__codelineno-34-2" href="#__codelineno-34-2"></a>
</span><span id="__span-34-3"><a id="__codelineno-34-3" name="__codelineno-34-3" href="#__codelineno-34-3"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi</span><span class="w"> </span><span class="kn">import</span> <span class="n">Depends</span>
</span><span id="__span-34-4"><a id="__codelineno-34-4" name="__codelineno-34-4" href="#__codelineno-34-4"></a>
</span><span id="__span-34-5"><a id="__codelineno-34-5" name="__codelineno-34-5" href="#__codelineno-34-5"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
</span><span id="__span-34-6"><a id="__codelineno-34-6" name="__codelineno-34-6" href="#__codelineno-34-6"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">list_users</span><span class="p">(</span>
</span><span id="__span-34-7"><a id="__codelineno-34-7" name="__codelineno-34-7" href="#__codelineno-34-7"></a> <span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span>
</span><span id="__span-34-8"><a id="__codelineno-34-8" name="__codelineno-34-8" href="#__codelineno-34-8"></a> <span class="n">params</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">dict</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate_params</span><span class="p">())],</span>
</span><span id="__span-34-9"><a id="__codelineno-34-9" name="__codelineno-34-9" href="#__codelineno-34-9"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">OffsetPaginatedResponse</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-34-10"><a id="__codelineno-34-10" name="__codelineno-34-10" href="#__codelineno-34-10"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">)</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-35-1"><a id="__codelineno-35-1" name="__codelineno-35-1" href="#__codelineno-35-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Annotated</span>
</span><span id="__span-35-2"><a id="__codelineno-35-2" name="__codelineno-35-2" href="#__codelineno-35-2"></a>
</span><span id="__span-35-3"><a id="__codelineno-35-3" name="__codelineno-35-3" href="#__codelineno-35-3"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi</span><span class="w"> </span><span class="kn">import</span> <span class="n">Depends</span>
</span><span id="__span-35-4"><a id="__codelineno-35-4" name="__codelineno-35-4" href="#__codelineno-35-4"></a>
</span><span id="__span-35-5"><a id="__codelineno-35-5" name="__codelineno-35-5" href="#__codelineno-35-5"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
</span><span id="__span-35-6"><a id="__codelineno-35-6" name="__codelineno-35-6" href="#__codelineno-35-6"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">list_users</span><span class="p">(</span>
</span><span id="__span-35-7"><a id="__codelineno-35-7" name="__codelineno-35-7" href="#__codelineno-35-7"></a> <span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span>
</span><span id="__span-35-8"><a id="__codelineno-35-8" name="__codelineno-35-8" href="#__codelineno-35-8"></a> <span class="n">params</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">dict</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate_params</span><span class="p">())],</span>
</span><span id="__span-35-9"><a id="__codelineno-35-9" name="__codelineno-35-9" href="#__codelineno-35-9"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">OffsetPaginatedResponse</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-35-10"><a id="__codelineno-35-10" name="__codelineno-35-10" href="#__codelineno-35-10"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">)</span>
</span></code></pre></div>
<div class="language-python highlight"><pre><span></span><code><span id="__span-35-1"><a id="__codelineno-35-1" name="__codelineno-35-1" href="#__codelineno-35-1"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
</span><span id="__span-35-2"><a id="__codelineno-35-2" name="__codelineno-35-2" href="#__codelineno-35-2"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">list_users</span><span class="p">(</span>
</span><span id="__span-35-3"><a id="__codelineno-35-3" name="__codelineno-35-3" href="#__codelineno-35-3"></a> <span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span>
</span><span id="__span-35-4"><a id="__codelineno-35-4" name="__codelineno-35-4" href="#__codelineno-35-4"></a> <span class="n">params</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">dict</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">cursor_paginate_params</span><span class="p">())],</span>
</span><span id="__span-35-5"><a id="__codelineno-35-5" name="__codelineno-35-5" href="#__codelineno-35-5"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">CursorPaginatedResponse</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-35-6"><a id="__codelineno-35-6" name="__codelineno-35-6" href="#__codelineno-35-6"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">cursor_paginate</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">)</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-36-1"><a id="__codelineno-36-1" name="__codelineno-36-1" href="#__codelineno-36-1"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
</span><span id="__span-36-2"><a id="__codelineno-36-2" name="__codelineno-36-2" href="#__codelineno-36-2"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">list_users</span><span class="p">(</span>
</span><span id="__span-36-3"><a id="__codelineno-36-3" name="__codelineno-36-3" href="#__codelineno-36-3"></a> <span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span>
</span><span id="__span-36-4"><a id="__codelineno-36-4" name="__codelineno-36-4" href="#__codelineno-36-4"></a> <span class="n">params</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">dict</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">cursor_paginate_params</span><span class="p">())],</span>
</span><span id="__span-36-5"><a id="__codelineno-36-5" name="__codelineno-36-5" href="#__codelineno-36-5"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">CursorPaginatedResponse</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-36-6"><a id="__codelineno-36-6" name="__codelineno-36-6" href="#__codelineno-36-6"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">cursor_paginate</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">)</span>
</span></code></pre></div>
<p>The dependency adds two query parameters to the endpoint:</p>
<table>
@@ -2711,20 +2888,20 @@
</tr>
</tbody>
</table>
<div class="language-text highlight"><pre><span></span><code><span id="__span-36-1"><a id="__codelineno-36-1" name="__codelineno-36-1" href="#__codelineno-36-1"></a>GET /users?order_by=name&amp;order=asc → ORDER BY users.name ASC
</span><span id="__span-36-2"><a id="__codelineno-36-2" name="__codelineno-36-2" href="#__codelineno-36-2"></a>GET /users?order_by=role__name&amp;order=desc → LEFT JOIN roles ON ... ORDER BY roles.name DESC
<div class="language-text highlight"><pre><span></span><code><span id="__span-37-1"><a id="__codelineno-37-1" name="__codelineno-37-1" href="#__codelineno-37-1"></a>GET /users?order_by=name&amp;order=asc → ORDER BY users.name ASC
</span><span id="__span-37-2"><a id="__codelineno-37-2" name="__codelineno-37-2" href="#__codelineno-37-2"></a>GET /users?order_by=role__name&amp;order=desc → LEFT JOIN roles ON ... ORDER BY roles.name DESC
</span></code></pre></div>
<div class="admonition info">
<p class="admonition-title">Relationship tuples are joined automatically.</p>
<p>When a relation field is selected, the related table is LEFT OUTER JOINed automatically. An unknown <code>order_by</code> value raises <a href="../../reference/exceptions/#fastapi_toolsets.exceptions.exceptions.InvalidOrderFieldError"><code>InvalidOrderFieldError</code></a> (HTTP 422).</p>
</div>
<p>The available sort keys are returned in the <code>order_columns</code> field of <a href="../../reference/schemas/#fastapi_toolsets.schemas.PaginatedResponse"><code>PaginatedResponse</code></a>. Use them to populate a sort picker in the UI, or to validate <code>order_by</code> values on the client side:</p>
<div class="language-json highlight"><pre><span></span><code><span id="__span-37-1"><a id="__codelineno-37-1" name="__codelineno-37-1" href="#__codelineno-37-1"></a><span class="p">{</span>
</span><span id="__span-37-2"><a id="__codelineno-37-2" name="__codelineno-37-2" href="#__codelineno-37-2"></a><span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;SUCCESS&quot;</span><span class="p">,</span>
</span><span id="__span-37-3"><a id="__codelineno-37-3" name="__codelineno-37-3" href="#__codelineno-37-3"></a><span class="w"> </span><span class="nt">&quot;data&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;...&quot;</span><span class="p">],</span>
</span><span id="__span-37-4"><a id="__codelineno-37-4" name="__codelineno-37-4" href="#__codelineno-37-4"></a><span class="w"> </span><span class="nt">&quot;pagination&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="s2">&quot;...&quot;</span><span class="w"> </span><span class="p">},</span>
</span><span id="__span-37-5"><a id="__codelineno-37-5" name="__codelineno-37-5" href="#__codelineno-37-5"></a><span class="w"> </span><span class="nt">&quot;order_columns&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;created_at&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;name&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;role__name&quot;</span><span class="p">]</span>
</span><span id="__span-37-6"><a id="__codelineno-37-6" name="__codelineno-37-6" href="#__codelineno-37-6"></a><span class="p">}</span>
<div class="language-json highlight"><pre><span></span><code><span id="__span-38-1"><a id="__codelineno-38-1" name="__codelineno-38-1" href="#__codelineno-38-1"></a><span class="p">{</span>
</span><span id="__span-38-2"><a id="__codelineno-38-2" name="__codelineno-38-2" href="#__codelineno-38-2"></a><span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;SUCCESS&quot;</span><span class="p">,</span>
</span><span id="__span-38-3"><a id="__codelineno-38-3" name="__codelineno-38-3" href="#__codelineno-38-3"></a><span class="w"> </span><span class="nt">&quot;data&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;...&quot;</span><span class="p">],</span>
</span><span id="__span-38-4"><a id="__codelineno-38-4" name="__codelineno-38-4" href="#__codelineno-38-4"></a><span class="w"> </span><span class="nt">&quot;pagination&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="s2">&quot;...&quot;</span><span class="w"> </span><span class="p">},</span>
</span><span id="__span-38-5"><a id="__codelineno-38-5" name="__codelineno-38-5" href="#__codelineno-38-5"></a><span class="w"> </span><span class="nt">&quot;order_columns&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;created_at&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;name&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;role__name&quot;</span><span class="p">]</span>
</span><span id="__span-38-6"><a id="__codelineno-38-6" name="__codelineno-38-6" href="#__codelineno-38-6"></a><span class="p">}</span>
</span></code></pre></div>
<div class="admonition info">
<p class="admonition-title">Key format uses <code>__</code> as a separator for relationship chains.</p>
@@ -2739,71 +2916,71 @@
<p class="admonition-title">Warning</p>
<p>Avoid using <code>lazy="selectin"</code> on model relationships. It fires silently on every query, cannot be disabled per-call, and can cause unexpected cascading loads through deep relationship chains. Use <code>default_load_options</code> instead.</p>
</div>
<div class="language-python highlight"><pre><span></span><code><span id="__span-38-1"><a id="__codelineno-38-1" name="__codelineno-38-1" href="#__codelineno-38-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy.orm</span><span class="w"> </span><span class="kn">import</span> <span class="n">selectinload</span>
</span><span id="__span-38-2"><a id="__codelineno-38-2" name="__codelineno-38-2" href="#__codelineno-38-2"></a>
</span><span id="__span-38-3"><a id="__codelineno-38-3" name="__codelineno-38-3" href="#__codelineno-38-3"></a><span class="n">ArticleCrud</span> <span class="o">=</span> <span class="n">CrudFactory</span><span class="p">(</span>
</span><span id="__span-38-4"><a id="__codelineno-38-4" name="__codelineno-38-4" href="#__codelineno-38-4"></a> <span class="n">model</span><span class="o">=</span><span class="n">Article</span><span class="p">,</span>
</span><span id="__span-38-5"><a id="__codelineno-38-5" name="__codelineno-38-5" href="#__codelineno-38-5"></a> <span class="n">default_load_options</span><span class="o">=</span><span class="p">[</span>
</span><span id="__span-38-6"><a id="__codelineno-38-6" name="__codelineno-38-6" href="#__codelineno-38-6"></a> <span class="n">selectinload</span><span class="p">(</span><span class="n">Article</span><span class="o">.</span><span class="n">category</span><span class="p">),</span>
</span><span id="__span-38-7"><a id="__codelineno-38-7" name="__codelineno-38-7" href="#__codelineno-38-7"></a> <span class="n">selectinload</span><span class="p">(</span><span class="n">Article</span><span class="o">.</span><span class="n">tags</span><span class="p">),</span>
</span><span id="__span-38-8"><a id="__codelineno-38-8" name="__codelineno-38-8" href="#__codelineno-38-8"></a> <span class="p">],</span>
</span><span id="__span-38-9"><a id="__codelineno-38-9" name="__codelineno-38-9" href="#__codelineno-38-9"></a><span class="p">)</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-39-1"><a id="__codelineno-39-1" name="__codelineno-39-1" href="#__codelineno-39-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy.orm</span><span class="w"> </span><span class="kn">import</span> <span class="n">selectinload</span>
</span><span id="__span-39-2"><a id="__codelineno-39-2" name="__codelineno-39-2" href="#__codelineno-39-2"></a>
</span><span id="__span-39-3"><a id="__codelineno-39-3" name="__codelineno-39-3" href="#__codelineno-39-3"></a><span class="n">ArticleCrud</span> <span class="o">=</span> <span class="n">CrudFactory</span><span class="p">(</span>
</span><span id="__span-39-4"><a id="__codelineno-39-4" name="__codelineno-39-4" href="#__codelineno-39-4"></a> <span class="n">model</span><span class="o">=</span><span class="n">Article</span><span class="p">,</span>
</span><span id="__span-39-5"><a id="__codelineno-39-5" name="__codelineno-39-5" href="#__codelineno-39-5"></a> <span class="n">default_load_options</span><span class="o">=</span><span class="p">[</span>
</span><span id="__span-39-6"><a id="__codelineno-39-6" name="__codelineno-39-6" href="#__codelineno-39-6"></a> <span class="n">selectinload</span><span class="p">(</span><span class="n">Article</span><span class="o">.</span><span class="n">category</span><span class="p">),</span>
</span><span id="__span-39-7"><a id="__codelineno-39-7" name="__codelineno-39-7" href="#__codelineno-39-7"></a> <span class="n">selectinload</span><span class="p">(</span><span class="n">Article</span><span class="o">.</span><span class="n">tags</span><span class="p">),</span>
</span><span id="__span-39-8"><a id="__codelineno-39-8" name="__codelineno-39-8" href="#__codelineno-39-8"></a> <span class="p">],</span>
</span><span id="__span-39-9"><a id="__codelineno-39-9" name="__codelineno-39-9" href="#__codelineno-39-9"></a><span class="p">)</span>
</span></code></pre></div>
<p><code>default_load_options</code> applies automatically to all read operations (<code>get</code>, <code>first</code>, <code>get_multi</code>, <code>offset_paginate</code>, <code>cursor_paginate</code>). When <code>load_options</code> is passed at call-site, it <strong>fully replaces</strong> <code>default_load_options</code> for that query — giving you precise per-call control:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-39-1"><a id="__codelineno-39-1" name="__codelineno-39-1" href="#__codelineno-39-1"></a><span class="c1"># Only loads category, tags are not loaded</span>
</span><span id="__span-39-2"><a id="__codelineno-39-2" name="__codelineno-39-2" href="#__codelineno-39-2"></a><span class="n">article</span> <span class="o">=</span> <span class="k">await</span> <span class="n">ArticleCrud</span><span class="o">.</span><span class="n">get</span><span class="p">(</span>
</span><span id="__span-39-3"><a id="__codelineno-39-3" name="__codelineno-39-3" href="#__codelineno-39-3"></a> <span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span>
</span><span id="__span-39-4"><a id="__codelineno-39-4" name="__codelineno-39-4" href="#__codelineno-39-4"></a> <span class="n">filters</span><span class="o">=</span><span class="p">[</span><span class="n">Article</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">article_id</span><span class="p">],</span>
</span><span id="__span-39-5"><a id="__codelineno-39-5" name="__codelineno-39-5" href="#__codelineno-39-5"></a> <span class="n">load_options</span><span class="o">=</span><span class="p">[</span><span class="n">selectinload</span><span class="p">(</span><span class="n">Article</span><span class="o">.</span><span class="n">category</span><span class="p">)],</span>
</span><span id="__span-39-6"><a id="__codelineno-39-6" name="__codelineno-39-6" href="#__codelineno-39-6"></a><span class="p">)</span>
</span><span id="__span-39-7"><a id="__codelineno-39-7" name="__codelineno-39-7" href="#__codelineno-39-7"></a>
</span><span id="__span-39-8"><a id="__codelineno-39-8" name="__codelineno-39-8" href="#__codelineno-39-8"></a><span class="c1"># Loads nothing — useful for write-then-refresh flows or lightweight checks</span>
</span><span id="__span-39-9"><a id="__codelineno-39-9" name="__codelineno-39-9" href="#__codelineno-39-9"></a><span class="n">articles</span> <span class="o">=</span> <span class="k">await</span> <span class="n">ArticleCrud</span><span class="o">.</span><span class="n">get_multi</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="n">load_options</span><span class="o">=</span><span class="p">[])</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-40-1"><a id="__codelineno-40-1" name="__codelineno-40-1" href="#__codelineno-40-1"></a><span class="c1"># Only loads category, tags are not loaded</span>
</span><span id="__span-40-2"><a id="__codelineno-40-2" name="__codelineno-40-2" href="#__codelineno-40-2"></a><span class="n">article</span> <span class="o">=</span> <span class="k">await</span> <span class="n">ArticleCrud</span><span class="o">.</span><span class="n">get</span><span class="p">(</span>
</span><span id="__span-40-3"><a id="__codelineno-40-3" name="__codelineno-40-3" href="#__codelineno-40-3"></a> <span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span>
</span><span id="__span-40-4"><a id="__codelineno-40-4" name="__codelineno-40-4" href="#__codelineno-40-4"></a> <span class="n">filters</span><span class="o">=</span><span class="p">[</span><span class="n">Article</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">article_id</span><span class="p">],</span>
</span><span id="__span-40-5"><a id="__codelineno-40-5" name="__codelineno-40-5" href="#__codelineno-40-5"></a> <span class="n">load_options</span><span class="o">=</span><span class="p">[</span><span class="n">selectinload</span><span class="p">(</span><span class="n">Article</span><span class="o">.</span><span class="n">category</span><span class="p">)],</span>
</span><span id="__span-40-6"><a id="__codelineno-40-6" name="__codelineno-40-6" href="#__codelineno-40-6"></a><span class="p">)</span>
</span><span id="__span-40-7"><a id="__codelineno-40-7" name="__codelineno-40-7" href="#__codelineno-40-7"></a>
</span><span id="__span-40-8"><a id="__codelineno-40-8" name="__codelineno-40-8" href="#__codelineno-40-8"></a><span class="c1"># Loads nothing — useful for write-then-refresh flows or lightweight checks</span>
</span><span id="__span-40-9"><a id="__codelineno-40-9" name="__codelineno-40-9" href="#__codelineno-40-9"></a><span class="n">articles</span> <span class="o">=</span> <span class="k">await</span> <span class="n">ArticleCrud</span><span class="o">.</span><span class="n">get_multi</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="n">load_options</span><span class="o">=</span><span class="p">[])</span>
</span></code></pre></div>
<h2 id="many-to-many-relationships">Many-to-many relationships<a class="headerlink" href="#many-to-many-relationships" title="Permanent link">&para;</a></h2>
<p>Use <code>m2m_fields</code> to map schema fields containing lists of IDs to SQLAlchemy relationships. The CRUD class resolves and validates all IDs before persisting:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-40-1"><a id="__codelineno-40-1" name="__codelineno-40-1" href="#__codelineno-40-1"></a><span class="n">PostCrud</span> <span class="o">=</span> <span class="n">CrudFactory</span><span class="p">(</span>
</span><span id="__span-40-2"><a id="__codelineno-40-2" name="__codelineno-40-2" href="#__codelineno-40-2"></a> <span class="n">model</span><span class="o">=</span><span class="n">Post</span><span class="p">,</span>
</span><span id="__span-40-3"><a id="__codelineno-40-3" name="__codelineno-40-3" href="#__codelineno-40-3"></a> <span class="n">m2m_fields</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;tag_ids&quot;</span><span class="p">:</span> <span class="n">Post</span><span class="o">.</span><span class="n">tags</span><span class="p">},</span>
</span><span id="__span-40-4"><a id="__codelineno-40-4" name="__codelineno-40-4" href="#__codelineno-40-4"></a><span class="p">)</span>
</span><span id="__span-40-5"><a id="__codelineno-40-5" name="__codelineno-40-5" href="#__codelineno-40-5"></a>
</span><span id="__span-40-6"><a id="__codelineno-40-6" name="__codelineno-40-6" href="#__codelineno-40-6"></a><span class="n">post</span> <span class="o">=</span> <span class="k">await</span> <span class="n">PostCrud</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="n">obj</span><span class="o">=</span><span class="n">PostCreateSchema</span><span class="p">(</span><span class="n">title</span><span class="o">=</span><span class="s2">&quot;Hello&quot;</span><span class="p">,</span> <span class="n">tag_ids</span><span class="o">=</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]))</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-41-1"><a id="__codelineno-41-1" name="__codelineno-41-1" href="#__codelineno-41-1"></a><span class="n">PostCrud</span> <span class="o">=</span> <span class="n">CrudFactory</span><span class="p">(</span>
</span><span id="__span-41-2"><a id="__codelineno-41-2" name="__codelineno-41-2" href="#__codelineno-41-2"></a> <span class="n">model</span><span class="o">=</span><span class="n">Post</span><span class="p">,</span>
</span><span id="__span-41-3"><a id="__codelineno-41-3" name="__codelineno-41-3" href="#__codelineno-41-3"></a> <span class="n">m2m_fields</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;tag_ids&quot;</span><span class="p">:</span> <span class="n">Post</span><span class="o">.</span><span class="n">tags</span><span class="p">},</span>
</span><span id="__span-41-4"><a id="__codelineno-41-4" name="__codelineno-41-4" href="#__codelineno-41-4"></a><span class="p">)</span>
</span><span id="__span-41-5"><a id="__codelineno-41-5" name="__codelineno-41-5" href="#__codelineno-41-5"></a>
</span><span id="__span-41-6"><a id="__codelineno-41-6" name="__codelineno-41-6" href="#__codelineno-41-6"></a><span class="n">post</span> <span class="o">=</span> <span class="k">await</span> <span class="n">PostCrud</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="n">obj</span><span class="o">=</span><span class="n">PostCreateSchema</span><span class="p">(</span><span class="n">title</span><span class="o">=</span><span class="s2">&quot;Hello&quot;</span><span class="p">,</span> <span class="n">tag_ids</span><span class="o">=</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]))</span>
</span></code></pre></div>
<h2 id="upsert">Upsert<a class="headerlink" href="#upsert" title="Permanent link">&para;</a></h2>
<p>Atomic <code>INSERT ... ON CONFLICT DO UPDATE</code> using PostgreSQL:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-41-1"><a id="__codelineno-41-1" name="__codelineno-41-1" href="#__codelineno-41-1"></a><span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">upsert</span><span class="p">(</span>
</span><span id="__span-41-2"><a id="__codelineno-41-2" name="__codelineno-41-2" href="#__codelineno-41-2"></a> <span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span>
</span><span id="__span-41-3"><a id="__codelineno-41-3" name="__codelineno-41-3" href="#__codelineno-41-3"></a> <span class="n">obj</span><span class="o">=</span><span class="n">UserCreateSchema</span><span class="p">(</span><span class="n">email</span><span class="o">=</span><span class="s2">&quot;alice@example.com&quot;</span><span class="p">,</span> <span class="n">username</span><span class="o">=</span><span class="s2">&quot;alice&quot;</span><span class="p">),</span>
</span><span id="__span-41-4"><a id="__codelineno-41-4" name="__codelineno-41-4" href="#__codelineno-41-4"></a> <span class="n">index_elements</span><span class="o">=</span><span class="p">[</span><span class="n">User</span><span class="o">.</span><span class="n">email</span><span class="p">],</span>
</span><span id="__span-41-5"><a id="__codelineno-41-5" name="__codelineno-41-5" href="#__codelineno-41-5"></a> <span class="n">set_</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;username&quot;</span><span class="p">},</span>
</span><span id="__span-41-6"><a id="__codelineno-41-6" name="__codelineno-41-6" href="#__codelineno-41-6"></a><span class="p">)</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-42-1"><a id="__codelineno-42-1" name="__codelineno-42-1" href="#__codelineno-42-1"></a><span class="k">await</span> <span class="n">UserCrud</span><span class="o">.</span><span class="n">upsert</span><span class="p">(</span>
</span><span id="__span-42-2"><a id="__codelineno-42-2" name="__codelineno-42-2" href="#__codelineno-42-2"></a> <span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span>
</span><span id="__span-42-3"><a id="__codelineno-42-3" name="__codelineno-42-3" href="#__codelineno-42-3"></a> <span class="n">obj</span><span class="o">=</span><span class="n">UserCreateSchema</span><span class="p">(</span><span class="n">email</span><span class="o">=</span><span class="s2">&quot;alice@example.com&quot;</span><span class="p">,</span> <span class="n">username</span><span class="o">=</span><span class="s2">&quot;alice&quot;</span><span class="p">),</span>
</span><span id="__span-42-4"><a id="__codelineno-42-4" name="__codelineno-42-4" href="#__codelineno-42-4"></a> <span class="n">index_elements</span><span class="o">=</span><span class="p">[</span><span class="n">User</span><span class="o">.</span><span class="n">email</span><span class="p">],</span>
</span><span id="__span-42-5"><a id="__codelineno-42-5" name="__codelineno-42-5" href="#__codelineno-42-5"></a> <span class="n">set_</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;username&quot;</span><span class="p">},</span>
</span><span id="__span-42-6"><a id="__codelineno-42-6" name="__codelineno-42-6" href="#__codelineno-42-6"></a><span class="p">)</span>
</span></code></pre></div>
<h2 id="response-serialization">Response serialization<a class="headerlink" href="#response-serialization" title="Permanent link">&para;</a></h2>
<div class="admonition info">
<p class="admonition-title">Added in <code>v1.1</code></p>
</div>
<p>Pass a Pydantic schema class to <code>create</code>, <code>get</code>, <code>update</code>, or <code>offset_paginate</code> to serialize the result directly into that schema and wrap it in a <a href="../../reference/schemas/#fastapi_toolsets.schemas.Response"><code>Response[schema]</code></a> or <a href="../../reference/schemas/#fastapi_toolsets.schemas.PaginatedResponse"><code>PaginatedResponse[schema]</code></a>:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-42-1"><a id="__codelineno-42-1" name="__codelineno-42-1" href="#__codelineno-42-1"></a><span class="k">class</span><span class="w"> </span><span class="nc">UserRead</span><span class="p">(</span><span class="n">PydanticBase</span><span class="p">):</span>
</span><span id="__span-42-2"><a id="__codelineno-42-2" name="__codelineno-42-2" href="#__codelineno-42-2"></a> <span class="nb">id</span><span class="p">:</span> <span class="n">UUID</span>
</span><span id="__span-42-3"><a id="__codelineno-42-3" name="__codelineno-42-3" href="#__codelineno-42-3"></a> <span class="n">username</span><span class="p">:</span> <span class="nb">str</span>
</span><span id="__span-42-4"><a id="__codelineno-42-4" name="__codelineno-42-4" href="#__codelineno-42-4"></a>
</span><span id="__span-42-5"><a id="__codelineno-42-5" name="__codelineno-42-5" href="#__codelineno-42-5"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span>
</span><span id="__span-42-6"><a id="__codelineno-42-6" name="__codelineno-42-6" href="#__codelineno-42-6"></a> <span class="s2">&quot;/</span><span class="si">{uuid}</span><span class="s2">&quot;</span><span class="p">,</span>
</span><span id="__span-42-7"><a id="__codelineno-42-7" name="__codelineno-42-7" href="#__codelineno-42-7"></a> <span class="n">responses</span><span class="o">=</span><span class="n">generate_error_responses</span><span class="p">(</span><span class="n">NotFoundError</span><span class="p">),</span>
</span><span id="__span-42-8"><a id="__codelineno-42-8" name="__codelineno-42-8" href="#__codelineno-42-8"></a><span class="p">)</span>
</span><span id="__span-42-9"><a id="__codelineno-42-9" name="__codelineno-42-9" href="#__codelineno-42-9"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">get_user</span><span class="p">(</span><span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span> <span class="n">uuid</span><span class="p">:</span> <span class="n">UUID</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Response</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-42-10"><a id="__codelineno-42-10" name="__codelineno-42-10" href="#__codelineno-42-10"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">crud</span><span class="o">.</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">get</span><span class="p">(</span>
</span><span id="__span-42-11"><a id="__codelineno-42-11" name="__codelineno-42-11" href="#__codelineno-42-11"></a> <span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span>
</span><span id="__span-42-12"><a id="__codelineno-42-12" name="__codelineno-42-12" href="#__codelineno-42-12"></a> <span class="n">filters</span><span class="o">=</span><span class="p">[</span><span class="n">User</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">uuid</span><span class="p">],</span>
</span><span id="__span-42-13"><a id="__codelineno-42-13" name="__codelineno-42-13" href="#__codelineno-42-13"></a> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">,</span>
</span><span id="__span-42-14"><a id="__codelineno-42-14" name="__codelineno-42-14" href="#__codelineno-42-14"></a> <span class="p">)</span>
</span><span id="__span-42-15"><a id="__codelineno-42-15" name="__codelineno-42-15" href="#__codelineno-42-15"></a>
</span><span id="__span-42-16"><a id="__codelineno-42-16" name="__codelineno-42-16" href="#__codelineno-42-16"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
</span><span id="__span-42-17"><a id="__codelineno-42-17" name="__codelineno-42-17" href="#__codelineno-42-17"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">list_users</span><span class="p">(</span>
</span><span id="__span-42-18"><a id="__codelineno-42-18" name="__codelineno-42-18" href="#__codelineno-42-18"></a> <span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span>
</span><span id="__span-42-19"><a id="__codelineno-42-19" name="__codelineno-42-19" href="#__codelineno-42-19"></a> <span class="n">params</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">dict</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">crud</span><span class="o">.</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate_params</span><span class="p">())],</span>
</span><span id="__span-42-20"><a id="__codelineno-42-20" name="__codelineno-42-20" href="#__codelineno-42-20"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">OffsetPaginatedResponse</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-42-21"><a id="__codelineno-42-21" name="__codelineno-42-21" href="#__codelineno-42-21"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">crud</span><span class="o">.</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">)</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-43-1"><a id="__codelineno-43-1" name="__codelineno-43-1" href="#__codelineno-43-1"></a><span class="k">class</span><span class="w"> </span><span class="nc">UserRead</span><span class="p">(</span><span class="n">PydanticBase</span><span class="p">):</span>
</span><span id="__span-43-2"><a id="__codelineno-43-2" name="__codelineno-43-2" href="#__codelineno-43-2"></a> <span class="nb">id</span><span class="p">:</span> <span class="n">UUID</span>
</span><span id="__span-43-3"><a id="__codelineno-43-3" name="__codelineno-43-3" href="#__codelineno-43-3"></a> <span class="n">username</span><span class="p">:</span> <span class="nb">str</span>
</span><span id="__span-43-4"><a id="__codelineno-43-4" name="__codelineno-43-4" href="#__codelineno-43-4"></a>
</span><span id="__span-43-5"><a id="__codelineno-43-5" name="__codelineno-43-5" href="#__codelineno-43-5"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span>
</span><span id="__span-43-6"><a id="__codelineno-43-6" name="__codelineno-43-6" href="#__codelineno-43-6"></a> <span class="s2">&quot;/</span><span class="si">{uuid}</span><span class="s2">&quot;</span><span class="p">,</span>
</span><span id="__span-43-7"><a id="__codelineno-43-7" name="__codelineno-43-7" href="#__codelineno-43-7"></a> <span class="n">responses</span><span class="o">=</span><span class="n">generate_error_responses</span><span class="p">(</span><span class="n">NotFoundError</span><span class="p">),</span>
</span><span id="__span-43-8"><a id="__codelineno-43-8" name="__codelineno-43-8" href="#__codelineno-43-8"></a><span class="p">)</span>
</span><span id="__span-43-9"><a id="__codelineno-43-9" name="__codelineno-43-9" href="#__codelineno-43-9"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">get_user</span><span class="p">(</span><span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span> <span class="n">uuid</span><span class="p">:</span> <span class="n">UUID</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Response</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-43-10"><a id="__codelineno-43-10" name="__codelineno-43-10" href="#__codelineno-43-10"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">crud</span><span class="o">.</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">get</span><span class="p">(</span>
</span><span id="__span-43-11"><a id="__codelineno-43-11" name="__codelineno-43-11" href="#__codelineno-43-11"></a> <span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span>
</span><span id="__span-43-12"><a id="__codelineno-43-12" name="__codelineno-43-12" href="#__codelineno-43-12"></a> <span class="n">filters</span><span class="o">=</span><span class="p">[</span><span class="n">User</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">uuid</span><span class="p">],</span>
</span><span id="__span-43-13"><a id="__codelineno-43-13" name="__codelineno-43-13" href="#__codelineno-43-13"></a> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">,</span>
</span><span id="__span-43-14"><a id="__codelineno-43-14" name="__codelineno-43-14" href="#__codelineno-43-14"></a> <span class="p">)</span>
</span><span id="__span-43-15"><a id="__codelineno-43-15" name="__codelineno-43-15" href="#__codelineno-43-15"></a>
</span><span id="__span-43-16"><a id="__codelineno-43-16" name="__codelineno-43-16" href="#__codelineno-43-16"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
</span><span id="__span-43-17"><a id="__codelineno-43-17" name="__codelineno-43-17" href="#__codelineno-43-17"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">list_users</span><span class="p">(</span>
</span><span id="__span-43-18"><a id="__codelineno-43-18" name="__codelineno-43-18" href="#__codelineno-43-18"></a> <span class="n">session</span><span class="p">:</span> <span class="n">SessionDep</span><span class="p">,</span>
</span><span id="__span-43-19"><a id="__codelineno-43-19" name="__codelineno-43-19" href="#__codelineno-43-19"></a> <span class="n">params</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">dict</span><span class="p">,</span> <span class="n">Depends</span><span class="p">(</span><span class="n">crud</span><span class="o">.</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate_params</span><span class="p">())],</span>
</span><span id="__span-43-20"><a id="__codelineno-43-20" name="__codelineno-43-20" href="#__codelineno-43-20"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">OffsetPaginatedResponse</span><span class="p">[</span><span class="n">UserRead</span><span class="p">]:</span>
</span><span id="__span-43-21"><a id="__codelineno-43-21" name="__codelineno-43-21" href="#__codelineno-43-21"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">crud</span><span class="o">.</span><span class="n">UserCrud</span><span class="o">.</span><span class="n">offset_paginate</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="n">UserRead</span><span class="p">)</span>
</span></code></pre></div>
<p>The schema must have <code>from_attributes=True</code> (or inherit from <a href="../../reference/schemas/#fastapi_toolsets.schemas.PydanticBase"><code>PydanticBase</code></a>) so it can be built from SQLAlchemy model instances.</p>
<hr />
@@ -2914,7 +3091,7 @@
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/module/db/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/module/db/">
<link rel="prev" href="../crud/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -231,6 +231,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="../cli/" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item">
<a href="../../reference/cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -600,10 +676,32 @@
</li>
<li class="md-nav__item">
<a href="#session-dependency" class="md-nav__link">
<a href="#setup" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
Session dependency
Setup
</span>
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#committing-before-the-response" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
Committing before the response
</span>
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lifespan" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
Lifespan
</span>
</span>
</a>
@@ -622,10 +720,10 @@
</li>
<li class="md-nav__item">
<a href="#nested-transactions" class="md-nav__link">
<a href="#transactions" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
Nested transactions
Transactions
</span>
</span>
</a>
@@ -641,6 +739,17 @@
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#advisory-locking" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
Advisory locking
</span>
</span>
</a>
</li>
<li class="md-nav__item">
@@ -692,7 +801,7 @@
<a href="#m2m_add-insert-associations" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
<code>m2m_add</code> insert associations
<code>m2m_add</code>: insert associations
</span>
</span>
</a>
@@ -703,7 +812,7 @@
<a href="#m2m_remove-delete-associations" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
<code>m2m_remove</code> delete associations
<code>m2m_remove</code>: delete associations
</span>
</span>
</a>
@@ -714,7 +823,7 @@
<a href="#m2m_set-replace-the-full-set" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
<code>m2m_set</code> replace the full set
<code>m2m_set</code>: replace the full set
</span>
</span>
</a>
@@ -1704,10 +1813,32 @@
</li>
<li class="md-nav__item">
<a href="#session-dependency" class="md-nav__link">
<a href="#setup" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
Session dependency
Setup
</span>
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#committing-before-the-response" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
Committing before the response
</span>
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lifespan" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
Lifespan
</span>
</span>
</a>
@@ -1726,10 +1857,10 @@
</li>
<li class="md-nav__item">
<a href="#nested-transactions" class="md-nav__link">
<a href="#transactions" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
Nested transactions
Transactions
</span>
</span>
</a>
@@ -1745,6 +1876,17 @@
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#advisory-locking" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
Advisory locking
</span>
</span>
</a>
</li>
<li class="md-nav__item">
@@ -1796,7 +1938,7 @@
<a href="#m2m_add-insert-associations" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
<code>m2m_add</code> insert associations
<code>m2m_add</code>: insert associations
</span>
</span>
</a>
@@ -1807,7 +1949,7 @@
<a href="#m2m_remove-delete-associations" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
<code>m2m_remove</code> delete associations
<code>m2m_remove</code>: delete associations
</span>
</span>
</a>
@@ -1818,7 +1960,7 @@
<a href="#m2m_set-replace-the-full-set" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
<code>m2m_set</code> replace the full set
<code>m2m_set</code>: replace the full set
</span>
</span>
</a>
@@ -1857,6 +1999,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -1872,9 +2015,39 @@
<li class="md-path__item">
<a href="../cli/" class="md-path__link">
<span class="md-ellipsis">
Modules
</span>
@@ -1905,125 +2078,182 @@
<h1 id="db">DB<a class="headerlink" href="#db" title="Permanent link">&para;</a></h1>
<p>SQLAlchemy async session management with transactions, table locking, and row-change polling.</p>
<p>SQLAlchemy async session management with transactions, table locking, advisory locking, and row-change polling.</p>
<div class="admonition info">
<p class="admonition-title">Info</p>
<p>This module has been coded and tested to be compatible with PostgreSQL only.</p>
</div>
<h2 id="overview">Overview<a class="headerlink" href="#overview" title="Permanent link">&para;</a></h2>
<p>The <code>db</code> module provides helpers to create FastAPI dependencies and context managers for <code>AsyncSession</code>, along with utilities for nested transactions, table lock and polling for row changes.</p>
<h2 id="session-dependency">Session dependency<a class="headerlink" href="#session-dependency" title="Permanent link">&para;</a></h2>
<p>Use <a href="../../reference/db/#fastapi_toolsets.db.create_db_dependency"><code>create_db_dependency</code></a> to create a FastAPI dependency that yields a session and auto-commits on success:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy.ext.asyncio</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_async_engine</span><span class="p">,</span> <span class="n">async_sessionmaker</span>
</span><span id="__span-0-2"><a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_db_dependency</span>
<p>The <code>db</code> module is built around one object, <a href="../../reference/db/#fastapi_toolsets.db.Database"><code>Database</code></a>, which owns the engine and sessionmaker and exposes the FastAPI dependency, a commit-before-response middleware, session/transaction context managers, and table locking. Free helpers cover savepoint-aware transactions, advisory locks, many-to-many association tables, and row-change polling.</p>
<h2 id="setup">Setup<a class="headerlink" href="#setup" title="Permanent link">&para;</a></h2>
<p>Create one <code>Database</code> for your app. Provide a <strong>URL</strong> (the facade builds and disposes the engine) or pass an existing <strong><code>engine=</code></strong> you own (e.g. for Alembic or <code>event.listen</code>). The session factory is built internally with <code>expire_on_commit=False</code>.</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi</span><span class="w"> </span><span class="kn">import</span> <span class="n">Depends</span><span class="p">,</span> <span class="n">FastAPI</span>
</span><span id="__span-0-2"><a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a><span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy.ext.asyncio</span><span class="w"> </span><span class="kn">import</span> <span class="n">AsyncSession</span>
</span><span id="__span-0-3"><a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a>
</span><span id="__span-0-4"><a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a><span class="n">engine</span> <span class="o">=</span> <span class="n">create_async_engine</span><span class="p">(</span><span class="n">url</span><span class="o">=</span><span class="s2">&quot;postgresql+asyncpg://...&quot;</span><span class="p">,</span> <span class="n">future</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="__span-0-5"><a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a><span class="n">session_maker</span> <span class="o">=</span> <span class="n">async_sessionmaker</span><span class="p">(</span><span class="n">bind</span><span class="o">=</span><span class="n">engine</span><span class="p">,</span> <span class="n">expire_on_commit</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
</span><span id="__span-0-6"><a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a>
</span><span id="__span-0-7"><a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a><span class="n">get_db</span> <span class="o">=</span> <span class="n">create_db_dependency</span><span class="p">(</span><span class="n">session_maker</span><span class="o">=</span><span class="n">session_maker</span><span class="p">)</span>
</span><span id="__span-0-8"><a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a>
</span><span id="__span-0-9"><a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a><span class="nd">@router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/users&quot;</span><span class="p">)</span>
</span><span id="__span-0-10"><a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">list_users</span><span class="p">(</span><span class="n">session</span><span class="p">:</span> <span class="n">AsyncSession</span> <span class="o">=</span> <span class="n">Depends</span><span class="p">(</span><span class="n">get_db</span><span class="p">)):</span>
</span><span id="__span-0-11"><a id="__codelineno-0-11" name="__codelineno-0-11" href="#__codelineno-0-11"></a> <span class="o">...</span>
</span><span id="__span-0-4"><a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">Database</span>
</span><span id="__span-0-5"><a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a>
</span><span id="__span-0-6"><a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a><span class="n">db</span> <span class="o">=</span> <span class="n">Database</span><span class="p">(</span><span class="s2">&quot;postgresql+asyncpg://postgres:postgres@localhost/app&quot;</span><span class="p">)</span>
</span><span id="__span-0-7"><a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a>
</span><span id="__span-0-8"><a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a><span class="n">app</span> <span class="o">=</span> <span class="n">FastAPI</span><span class="p">()</span>
</span><span id="__span-0-9"><a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a><span class="n">db</span><span class="o">.</span><span class="n">install</span><span class="p">(</span><span class="n">app</span><span class="p">)</span> <span class="c1"># commit middleware + engine disposal on shutdown</span>
</span><span id="__span-0-10"><a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a>
</span><span id="__span-0-11"><a id="__codelineno-0-11" name="__codelineno-0-11" href="#__codelineno-0-11"></a><span class="nd">@app</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/users&quot;</span><span class="p">)</span>
</span><span id="__span-0-12"><a id="__codelineno-0-12" name="__codelineno-0-12" href="#__codelineno-0-12"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">list_users</span><span class="p">(</span><span class="n">session</span><span class="p">:</span> <span class="n">AsyncSession</span> <span class="o">=</span> <span class="n">Depends</span><span class="p">(</span><span class="n">db</span><span class="p">)):</span>
</span><span id="__span-0-13"><a id="__codelineno-0-13" name="__codelineno-0-13" href="#__codelineno-0-13"></a> <span class="o">...</span>
</span></code></pre></div>
<h2 id="session-context-manager">Session context manager<a class="headerlink" href="#session-context-manager" title="Permanent link">&para;</a></h2>
<p>Use <a href="../../reference/db/#fastapi_toolsets.db.create_db_context"><code>create_db_context</code></a> for sessions outside request handlers (e.g. background tasks, CLI commands):</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-1-1"><a id="__codelineno-1-1" name="__codelineno-1-1" href="#__codelineno-1-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_db_context</span>
<p>The <code>Database</code> instance <strong>is</strong> the dependency: use it directly as <code>Depends(db)</code>. The whole request runs as a single transaction (CRUD writes use savepoints under it).</p>
<h2 id="committing-before-the-response">Committing before the response<a class="headerlink" href="#committing-before-the-response" title="Permanent link">&para;</a></h2>
<p><a href="../../reference/db/#fastapi_toolsets.db.Database"><code>db.install(app)</code></a> adds a middleware that commits the request's session when the response starts, after the endpoint returns and before the body is sent. With the middleware installed, the dependency does not commit again.</p>
<p>The request is committed as a single transaction:</p>
<ul>
<li><strong>Read-after-write</strong>: a follow-up request sees the write.</li>
<li><strong>Atomicity</strong>: multi-write endpoints roll back as a unit on failure.</li>
<li><strong>Errors roll back</strong>: on a raised exception the session rolls back and nothing is committed.</li>
</ul>
<p>Without <code>install</code>, the session commits in the dependency teardown, which runs after the response has been sent.</p>
<div class="admonition warning">
<p class="admonition-title">Streaming / SSE endpoints</p>
<p>For a <code>StreamingResponse</code> / <code>EventSourceResponse</code>, the commit fires at the <strong>start</strong> of the stream. A stream that <strong>writes</strong> must open a short-lived session per write with <a href="#session-context-manager"><code>db.session()</code></a>; the start-time commit will not flush writes made later during the stream.</p>
</div>
<h2 id="lifespan">Lifespan<a class="headerlink" href="#lifespan" title="Permanent link">&para;</a></h2>
<p><code>db.install(app)</code> disposes the engine on shutdown, composing around your own lifespan:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-1-1"><a id="__codelineno-1-1" name="__codelineno-1-1" href="#__codelineno-1-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">contextlib</span><span class="w"> </span><span class="kn">import</span> <span class="n">asynccontextmanager</span>
</span><span id="__span-1-2"><a id="__codelineno-1-2" name="__codelineno-1-2" href="#__codelineno-1-2"></a>
</span><span id="__span-1-3"><a id="__codelineno-1-3" name="__codelineno-1-3" href="#__codelineno-1-3"></a><span class="n">db_context</span> <span class="o">=</span> <span class="n">create_db_context</span><span class="p">(</span><span class="n">session_maker</span><span class="o">=</span><span class="n">session_maker</span><span class="p">)</span>
</span><span id="__span-1-4"><a id="__codelineno-1-4" name="__codelineno-1-4" href="#__codelineno-1-4"></a>
</span><span id="__span-1-5"><a id="__codelineno-1-5" name="__codelineno-1-5" href="#__codelineno-1-5"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">seed</span><span class="p">():</span>
</span><span id="__span-1-6"><a id="__codelineno-1-6" name="__codelineno-1-6" href="#__codelineno-1-6"></a> <span class="k">async</span> <span class="k">with</span> <span class="n">db_context</span><span class="p">()</span> <span class="k">as</span> <span class="n">session</span><span class="p">:</span>
</span><span id="__span-1-7"><a id="__codelineno-1-7" name="__codelineno-1-7" href="#__codelineno-1-7"></a> <span class="o">...</span>
</span><span id="__span-1-3"><a id="__codelineno-1-3" name="__codelineno-1-3" href="#__codelineno-1-3"></a><span class="nd">@asynccontextmanager</span>
</span><span id="__span-1-4"><a id="__codelineno-1-4" name="__codelineno-1-4" href="#__codelineno-1-4"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">lifespan</span><span class="p">(</span><span class="n">app</span><span class="p">):</span>
</span><span id="__span-1-5"><a id="__codelineno-1-5" name="__codelineno-1-5" href="#__codelineno-1-5"></a> <span class="k">await</span> <span class="n">warm_cache</span><span class="p">()</span> <span class="c1"># your startup</span>
</span><span id="__span-1-6"><a id="__codelineno-1-6" name="__codelineno-1-6" href="#__codelineno-1-6"></a> <span class="k">yield</span>
</span><span id="__span-1-7"><a id="__codelineno-1-7" name="__codelineno-1-7" href="#__codelineno-1-7"></a> <span class="k">await</span> <span class="n">flush_metrics</span><span class="p">()</span> <span class="c1"># your shutdown</span>
</span><span id="__span-1-8"><a id="__codelineno-1-8" name="__codelineno-1-8" href="#__codelineno-1-8"></a>
</span><span id="__span-1-9"><a id="__codelineno-1-9" name="__codelineno-1-9" href="#__codelineno-1-9"></a><span class="n">app</span> <span class="o">=</span> <span class="n">FastAPI</span><span class="p">(</span><span class="n">lifespan</span><span class="o">=</span><span class="n">lifespan</span><span class="p">)</span>
</span><span id="__span-1-10"><a id="__codelineno-1-10" name="__codelineno-1-10" href="#__codelineno-1-10"></a><span class="n">db</span><span class="o">.</span><span class="n">install</span><span class="p">(</span><span class="n">app</span><span class="p">)</span> <span class="c1"># your shutdown runs first, then the engine is disposed</span>
</span></code></pre></div>
<h2 id="nested-transactions">Nested transactions<a class="headerlink" href="#nested-transactions" title="Permanent link">&para;</a></h2>
<p><a href="../../reference/db/#fastapi_toolsets.db.get_transaction"><code>get_transaction</code></a> handles savepoints automatically, allowing safe nesting:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-2-1"><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">get_transaction</span>
</span><span id="__span-2-2"><a id="__codelineno-2-2" name="__codelineno-2-2" href="#__codelineno-2-2"></a>
</span><span id="__span-2-3"><a id="__codelineno-2-3" name="__codelineno-2-3" href="#__codelineno-2-3"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">create_user_with_role</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">):</span>
</span><span id="__span-2-4"><a id="__codelineno-2-4" name="__codelineno-2-4" href="#__codelineno-2-4"></a> <span class="k">async</span> <span class="k">with</span> <span class="n">get_transaction</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">):</span>
</span><span id="__span-2-5"><a id="__codelineno-2-5" name="__codelineno-2-5" href="#__codelineno-2-5"></a> <span class="o">...</span>
</span><span id="__span-2-6"><a id="__codelineno-2-6" name="__codelineno-2-6" href="#__codelineno-2-6"></a> <span class="k">async</span> <span class="k">with</span> <span class="n">get_transaction</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">):</span> <span class="c1"># uses savepoint</span>
</span><span id="__span-2-7"><a id="__codelineno-2-7" name="__codelineno-2-7" href="#__codelineno-2-7"></a> <span class="o">...</span>
<p>If you have no lifespan of your own, <a href="../../reference/db/#fastapi_toolsets.db.Database"><code>db.lifespan</code></a> works standalone as <code>FastAPI(lifespan=db.lifespan)</code>. Engine disposal is idempotent and is a no-op when you passed your own <code>engine=</code>.</p>
<h2 id="session-context-manager">Session context manager<a class="headerlink" href="#session-context-manager" title="Permanent link">&para;</a></h2>
<p>Use <a href="../../reference/db/#fastapi_toolsets.db.Database"><code>db.session()</code></a> for sessions outside request handlers (e.g. background tasks, CLI commands). It commits on clean exit and rolls back on exception:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-2-1"><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">seed</span><span class="p">():</span>
</span><span id="__span-2-2"><a id="__codelineno-2-2" name="__codelineno-2-2" href="#__codelineno-2-2"></a> <span class="k">async</span> <span class="k">with</span> <span class="n">db</span><span class="o">.</span><span class="n">session</span><span class="p">()</span> <span class="k">as</span> <span class="n">session</span><span class="p">:</span>
</span><span id="__span-2-3"><a id="__codelineno-2-3" name="__codelineno-2-3" href="#__codelineno-2-3"></a> <span class="o">...</span>
</span></code></pre></div>
<h2 id="transactions">Transactions<a class="headerlink" href="#transactions" title="Permanent link">&para;</a></h2>
<p><a href="../../reference/db/#fastapi_toolsets.db.transaction"><code>transaction</code></a> opens a transaction on a session, using a savepoint when one is already open so it nests safely:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-3-1"><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">transaction</span>
</span><span id="__span-3-2"><a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a>
</span><span id="__span-3-3"><a id="__codelineno-3-3" name="__codelineno-3-3" href="#__codelineno-3-3"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">create_user_with_role</span><span class="p">(</span><span class="n">session</span><span class="p">):</span>
</span><span id="__span-3-4"><a id="__codelineno-3-4" name="__codelineno-3-4" href="#__codelineno-3-4"></a> <span class="k">async</span> <span class="k">with</span> <span class="n">transaction</span><span class="p">(</span><span class="n">session</span><span class="p">):</span>
</span><span id="__span-3-5"><a id="__codelineno-3-5" name="__codelineno-3-5" href="#__codelineno-3-5"></a> <span class="o">...</span>
</span><span id="__span-3-6"><a id="__codelineno-3-6" name="__codelineno-3-6" href="#__codelineno-3-6"></a> <span class="k">async</span> <span class="k">with</span> <span class="n">transaction</span><span class="p">(</span><span class="n">session</span><span class="p">):</span> <span class="c1"># uses a savepoint</span>
</span><span id="__span-3-7"><a id="__codelineno-3-7" name="__codelineno-3-7" href="#__codelineno-3-7"></a> <span class="o">...</span>
</span></code></pre></div>
<p>When you have a <code>Database</code>, <a href="../../reference/db/#fastapi_toolsets.db.Database"><code>db.begin()</code></a> opens a session already inside a transaction:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-4-1"><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-1"></a><span class="k">async</span> <span class="k">with</span> <span class="n">db</span><span class="o">.</span><span class="n">begin</span><span class="p">()</span> <span class="k">as</span> <span class="n">session</span><span class="p">:</span>
</span><span id="__span-4-2"><a id="__codelineno-4-2" name="__codelineno-4-2" href="#__codelineno-4-2"></a> <span class="n">session</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">User</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">&quot;ada&quot;</span><span class="p">))</span> <span class="c1"># commits on exit, rolls back on exception</span>
</span></code></pre></div>
<h2 id="table-locking">Table locking<a class="headerlink" href="#table-locking" title="Permanent link">&para;</a></h2>
<p><a href="../../reference/db/#fastapi_toolsets.db.lock_tables"><code>lock_tables</code></a> acquires PostgreSQL table-level locks before executing critical sections. It opens a <strong>dedicated session</strong> internally and yields it to the caller, so the lock is guaranteed to be released when the context exits:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-3-1"><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">lock_tables</span><span class="p">,</span> <span class="n">LockMode</span>
</span><span id="__span-3-2"><a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a>
</span><span id="__span-3-3"><a id="__codelineno-3-3" name="__codelineno-3-3" href="#__codelineno-3-3"></a><span class="k">async</span> <span class="k">with</span> <span class="n">lock_tables</span><span class="p">(</span><span class="n">session_maker</span><span class="o">=</span><span class="n">session_maker</span><span class="p">,</span> <span class="n">tables</span><span class="o">=</span><span class="p">[</span><span class="n">User</span><span class="p">],</span> <span class="n">mode</span><span class="o">=</span><span class="n">LockMode</span><span class="o">.</span><span class="n">EXCLUSIVE</span><span class="p">)</span> <span class="k">as</span> <span class="n">session</span><span class="p">:</span>
</span><span id="__span-3-4"><a id="__codelineno-3-4" name="__codelineno-3-4" href="#__codelineno-3-4"></a> <span class="c1"># No other transaction can modify User until this block exits</span>
</span><span id="__span-3-5"><a id="__codelineno-3-5" name="__codelineno-3-5" href="#__codelineno-3-5"></a> <span class="o">...</span>
<p><a href="../../reference/db/#fastapi_toolsets.db.Database"><code>db.lock_tables</code></a> acquires PostgreSQL table-level locks for a critical section. It opens a dedicated session internally and releases the lock when the context exits:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-5-1"><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">LockMode</span>
</span><span id="__span-5-2"><a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a>
</span><span id="__span-5-3"><a id="__codelineno-5-3" name="__codelineno-5-3" href="#__codelineno-5-3"></a><span class="k">async</span> <span class="k">with</span> <span class="n">db</span><span class="o">.</span><span class="n">lock_tables</span><span class="p">([</span><span class="n">User</span><span class="p">],</span> <span class="n">mode</span><span class="o">=</span><span class="n">LockMode</span><span class="o">.</span><span class="n">EXCLUSIVE</span><span class="p">)</span> <span class="k">as</span> <span class="n">session</span><span class="p">:</span>
</span><span id="__span-5-4"><a id="__codelineno-5-4" name="__codelineno-5-4" href="#__codelineno-5-4"></a> <span class="c1"># No other transaction can modify User until this block exits</span>
</span><span id="__span-5-5"><a id="__codelineno-5-5" name="__codelineno-5-5" href="#__codelineno-5-5"></a> <span class="o">...</span>
</span></code></pre></div>
<p>Available lock modes are defined in <a href="../../reference/db/#fastapi_toolsets.db.LockMode"><code>LockMode</code></a>: <code>ACCESS_SHARE</code>, <code>ROW_SHARE</code>, <code>ROW_EXCLUSIVE</code>, <code>SHARE_UPDATE_EXCLUSIVE</code>, <code>SHARE</code>, <code>SHARE_ROW_EXCLUSIVE</code>, <code>EXCLUSIVE</code>, <code>ACCESS_EXCLUSIVE</code>.</p>
<p>Pass <code>timeout</code> to limit how long the lock waits. On timeout, a <a href="../../reference/exceptions/#fastapi_toolsets.exceptions.exceptions.LockTimeoutError"><code>LockTimeoutError</code></a> is raised instead of a raw database error:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-6-1"><a id="__codelineno-6-1" name="__codelineno-6-1" href="#__codelineno-6-1"></a><span class="k">async</span> <span class="k">with</span> <span class="n">db</span><span class="o">.</span><span class="n">lock_tables</span><span class="p">([</span><span class="n">Order</span><span class="p">],</span> <span class="n">timeout</span><span class="o">=</span><span class="s2">&quot;2s&quot;</span><span class="p">)</span> <span class="k">as</span> <span class="n">session</span><span class="p">:</span>
</span><span id="__span-6-2"><a id="__codelineno-6-2" name="__codelineno-6-2" href="#__codelineno-6-2"></a> <span class="o">...</span>
</span></code></pre></div>
<h2 id="advisory-locking">Advisory locking<a class="headerlink" href="#advisory-locking" title="Permanent link">&para;</a></h2>
<p><a href="../../reference/db/#fastapi_toolsets.db.advisory_lock"><code>advisory_lock</code></a> acquires a PostgreSQL session-level advisory lock on a session you provide. The lock is released when the context exits:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-7-1"><a id="__codelineno-7-1" name="__codelineno-7-1" href="#__codelineno-7-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">advisory_lock</span>
</span><span id="__span-7-2"><a id="__codelineno-7-2" name="__codelineno-7-2" href="#__codelineno-7-2"></a>
</span><span id="__span-7-3"><a id="__codelineno-7-3" name="__codelineno-7-3" href="#__codelineno-7-3"></a><span class="c1"># Blocking exclusive lock: waits until the lock is free</span>
</span><span id="__span-7-4"><a id="__codelineno-7-4" name="__codelineno-7-4" href="#__codelineno-7-4"></a><span class="k">async</span> <span class="k">with</span> <span class="n">advisory_lock</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="mi">42</span><span class="p">):</span>
</span><span id="__span-7-5"><a id="__codelineno-7-5" name="__codelineno-7-5" href="#__codelineno-7-5"></a> <span class="o">...</span>
</span><span id="__span-7-6"><a id="__codelineno-7-6" name="__codelineno-7-6" href="#__codelineno-7-6"></a>
</span><span id="__span-7-7"><a id="__codelineno-7-7" name="__codelineno-7-7" href="#__codelineno-7-7"></a><span class="c1"># Non-blocking: yields False immediately if already held</span>
</span><span id="__span-7-8"><a id="__codelineno-7-8" name="__codelineno-7-8" href="#__codelineno-7-8"></a><span class="k">async</span> <span class="k">with</span> <span class="n">advisory_lock</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="mi">42</span><span class="p">,</span> <span class="n">nowait</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> <span class="k">as</span> <span class="n">acquired</span><span class="p">:</span>
</span><span id="__span-7-9"><a id="__codelineno-7-9" name="__codelineno-7-9" href="#__codelineno-7-9"></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">acquired</span><span class="p">:</span>
</span><span id="__span-7-10"><a id="__codelineno-7-10" name="__codelineno-7-10" href="#__codelineno-7-10"></a> <span class="k">raise</span> <span class="n">HTTPException</span><span class="p">(</span><span class="mi">409</span><span class="p">,</span> <span class="s2">&quot;Resource is locked&quot;</span><span class="p">)</span>
</span><span id="__span-7-11"><a id="__codelineno-7-11" name="__codelineno-7-11" href="#__codelineno-7-11"></a>
</span><span id="__span-7-12"><a id="__codelineno-7-12" name="__codelineno-7-12" href="#__codelineno-7-12"></a><span class="c1"># Blocking with a timeout: raises LockTimeoutError if not acquired in time</span>
</span><span id="__span-7-13"><a id="__codelineno-7-13" name="__codelineno-7-13" href="#__codelineno-7-13"></a><span class="k">async</span> <span class="k">with</span> <span class="n">advisory_lock</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="mi">42</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="s2">&quot;5s&quot;</span><span class="p">):</span>
</span><span id="__span-7-14"><a id="__codelineno-7-14" name="__codelineno-7-14" href="#__codelineno-7-14"></a> <span class="o">...</span>
</span><span id="__span-7-15"><a id="__codelineno-7-15" name="__codelineno-7-15" href="#__codelineno-7-15"></a>
</span><span id="__span-7-16"><a id="__codelineno-7-16" name="__codelineno-7-16" href="#__codelineno-7-16"></a><span class="c1"># Shared lock: multiple readers allowed simultaneously, blocks exclusive writers</span>
</span><span id="__span-7-17"><a id="__codelineno-7-17" name="__codelineno-7-17" href="#__codelineno-7-17"></a><span class="k">async</span> <span class="k">with</span> <span class="n">advisory_lock</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="mi">42</span><span class="p">,</span> <span class="n">shared</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
</span><span id="__span-7-18"><a id="__codelineno-7-18" name="__codelineno-7-18" href="#__codelineno-7-18"></a> <span class="o">...</span>
</span><span id="__span-7-19"><a id="__codelineno-7-19" name="__codelineno-7-19" href="#__codelineno-7-19"></a>
</span><span id="__span-7-20"><a id="__codelineno-7-20" name="__codelineno-7-20" href="#__codelineno-7-20"></a><span class="c1"># Two-integer key for namespacing (e.g. lock_type + resource_id)</span>
</span><span id="__span-7-21"><a id="__codelineno-7-21" name="__codelineno-7-21" href="#__codelineno-7-21"></a><span class="k">async</span> <span class="k">with</span> <span class="n">advisory_lock</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">user_id</span><span class="p">)):</span>
</span><span id="__span-7-22"><a id="__codelineno-7-22" name="__codelineno-7-22" href="#__codelineno-7-22"></a> <span class="o">...</span>
</span></code></pre></div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Advisory locks use PostgreSQL session-level functions (<code>pg_advisory_lock</code> / <code>pg_advisory_unlock</code>). The lock is tied to the database connection, not the SQLAlchemy transaction, so it is released when the context exits even if the surrounding transaction is still open.</p>
</div>
<h2 id="row-change-polling">Row-change polling<a class="headerlink" href="#row-change-polling" title="Permanent link">&para;</a></h2>
<p><a href="../../reference/db/#fastapi_toolsets.db.wait_for_row_change"><code>wait_for_row_change</code></a> polls a row until a specific column changes value, useful for waiting on async side effects:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-4-1"><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">wait_for_row_change</span>
</span><span id="__span-4-2"><a id="__codelineno-4-2" name="__codelineno-4-2" href="#__codelineno-4-2"></a>
</span><span id="__span-4-3"><a id="__codelineno-4-3" name="__codelineno-4-3" href="#__codelineno-4-3"></a><span class="c1"># Wait up to 30s for order.status to change</span>
</span><span id="__span-4-4"><a id="__codelineno-4-4" name="__codelineno-4-4" href="#__codelineno-4-4"></a><span class="k">await</span> <span class="n">wait_for_row_change</span><span class="p">(</span>
</span><span id="__span-4-5"><a id="__codelineno-4-5" name="__codelineno-4-5" href="#__codelineno-4-5"></a> <span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span>
</span><span id="__span-4-6"><a id="__codelineno-4-6" name="__codelineno-4-6" href="#__codelineno-4-6"></a> <span class="n">model</span><span class="o">=</span><span class="n">Order</span><span class="p">,</span>
</span><span id="__span-4-7"><a id="__codelineno-4-7" name="__codelineno-4-7" href="#__codelineno-4-7"></a> <span class="n">pk_value</span><span class="o">=</span><span class="n">order_id</span><span class="p">,</span>
</span><span id="__span-4-8"><a id="__codelineno-4-8" name="__codelineno-4-8" href="#__codelineno-4-8"></a> <span class="n">columns</span><span class="o">=</span><span class="p">[</span><span class="n">Order</span><span class="o">.</span><span class="n">status</span><span class="p">],</span>
</span><span id="__span-4-9"><a id="__codelineno-4-9" name="__codelineno-4-9" href="#__codelineno-4-9"></a> <span class="n">interval</span><span class="o">=</span><span class="mf">1.0</span><span class="p">,</span>
</span><span id="__span-4-10"><a id="__codelineno-4-10" name="__codelineno-4-10" href="#__codelineno-4-10"></a> <span class="n">timeout</span><span class="o">=</span><span class="mf">30.0</span><span class="p">,</span>
</span><span id="__span-4-11"><a id="__codelineno-4-11" name="__codelineno-4-11" href="#__codelineno-4-11"></a><span class="p">)</span>
<p><a href="../../reference/db/#fastapi_toolsets.db.wait_for_row_change"><code>wait_for_row_change</code></a> polls a row until a specific column changes value:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-8-1"><a id="__codelineno-8-1" name="__codelineno-8-1" href="#__codelineno-8-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">wait_for_row_change</span>
</span><span id="__span-8-2"><a id="__codelineno-8-2" name="__codelineno-8-2" href="#__codelineno-8-2"></a>
</span><span id="__span-8-3"><a id="__codelineno-8-3" name="__codelineno-8-3" href="#__codelineno-8-3"></a><span class="c1"># Wait up to 30s for order.status to change</span>
</span><span id="__span-8-4"><a id="__codelineno-8-4" name="__codelineno-8-4" href="#__codelineno-8-4"></a><span class="k">await</span> <span class="n">wait_for_row_change</span><span class="p">(</span>
</span><span id="__span-8-5"><a id="__codelineno-8-5" name="__codelineno-8-5" href="#__codelineno-8-5"></a> <span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">,</span>
</span><span id="__span-8-6"><a id="__codelineno-8-6" name="__codelineno-8-6" href="#__codelineno-8-6"></a> <span class="n">model</span><span class="o">=</span><span class="n">Order</span><span class="p">,</span>
</span><span id="__span-8-7"><a id="__codelineno-8-7" name="__codelineno-8-7" href="#__codelineno-8-7"></a> <span class="n">pk_value</span><span class="o">=</span><span class="n">order_id</span><span class="p">,</span>
</span><span id="__span-8-8"><a id="__codelineno-8-8" name="__codelineno-8-8" href="#__codelineno-8-8"></a> <span class="n">columns</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;status&quot;</span><span class="p">],</span>
</span><span id="__span-8-9"><a id="__codelineno-8-9" name="__codelineno-8-9" href="#__codelineno-8-9"></a> <span class="n">interval</span><span class="o">=</span><span class="mf">1.0</span><span class="p">,</span>
</span><span id="__span-8-10"><a id="__codelineno-8-10" name="__codelineno-8-10" href="#__codelineno-8-10"></a> <span class="n">timeout</span><span class="o">=</span><span class="mf">30.0</span><span class="p">,</span>
</span><span id="__span-8-11"><a id="__codelineno-8-11" name="__codelineno-8-11" href="#__codelineno-8-11"></a><span class="p">)</span>
</span></code></pre></div>
<h2 id="creating-a-database">Creating a database<a class="headerlink" href="#creating-a-database" title="Permanent link">&para;</a></h2>
<div class="admonition info">
<p class="admonition-title">Added in <code>v2.1</code></p>
</div>
<p><a href="../../reference/db/#fastapi_toolsets.db.create_database"><code>create_database</code></a> creates a database at a given URL. It connects to <em>server_url</em> and issues a <code>CREATE DATABASE</code> statement:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-5-1"><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_database</span>
</span><span id="__span-5-2"><a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a>
</span><span id="__span-5-3"><a id="__codelineno-5-3" name="__codelineno-5-3" href="#__codelineno-5-3"></a><span class="n">SERVER_URL</span> <span class="o">=</span> <span class="s2">&quot;postgresql+asyncpg://postgres:postgres@localhost/postgres&quot;</span>
</span><span id="__span-5-4"><a id="__codelineno-5-4" name="__codelineno-5-4" href="#__codelineno-5-4"></a>
</span><span id="__span-5-5"><a id="__codelineno-5-5" name="__codelineno-5-5" href="#__codelineno-5-5"></a><span class="k">await</span> <span class="n">create_database</span><span class="p">(</span><span class="n">db_name</span><span class="o">=</span><span class="s2">&quot;myapp_test&quot;</span><span class="p">,</span> <span class="n">server_url</span><span class="o">=</span><span class="n">SERVER_URL</span><span class="p">)</span>
<p><a href="../../reference/db/#fastapi_toolsets.db.testing.create_database"><code>create_database</code></a> (in <code>fastapi_toolsets.db.testing</code>) connects to <em>server_url</em> and issues a <code>CREATE DATABASE</code> statement:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-9-1"><a id="__codelineno-9-1" name="__codelineno-9-1" href="#__codelineno-9-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db.testing</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_database</span>
</span><span id="__span-9-2"><a id="__codelineno-9-2" name="__codelineno-9-2" href="#__codelineno-9-2"></a>
</span><span id="__span-9-3"><a id="__codelineno-9-3" name="__codelineno-9-3" href="#__codelineno-9-3"></a><span class="n">SERVER_URL</span> <span class="o">=</span> <span class="s2">&quot;postgresql+asyncpg://postgres:postgres@localhost/postgres&quot;</span>
</span><span id="__span-9-4"><a id="__codelineno-9-4" name="__codelineno-9-4" href="#__codelineno-9-4"></a>
</span><span id="__span-9-5"><a id="__codelineno-9-5" name="__codelineno-9-5" href="#__codelineno-9-5"></a><span class="k">await</span> <span class="n">create_database</span><span class="p">(</span><span class="n">db_name</span><span class="o">=</span><span class="s2">&quot;myapp_test&quot;</span><span class="p">,</span> <span class="n">server_url</span><span class="o">=</span><span class="n">SERVER_URL</span><span class="p">)</span>
</span></code></pre></div>
<p>For test isolation with automatic cleanup, use <a href="../../reference/pytest/#fastapi_toolsets.pytest.utils.create_worker_database"><code>create_worker_database</code></a> from the <code>pytest</code> module instead — it handles drop-before, create, and drop-after automatically.</p>
<p>For test isolation with automatic cleanup, use <a href="../../reference/pytest/#fastapi_toolsets.pytest.utils.create_worker_database"><code>create_worker_database</code></a> from the <code>pytest</code> module, which handles drop-before, create, and drop-after.</p>
<h2 id="cleaning-up-tables">Cleaning up tables<a class="headerlink" href="#cleaning-up-tables" title="Permanent link">&para;</a></h2>
<div class="admonition info">
<p class="admonition-title">Added in <code>v2.1</code></p>
</div>
<p><a href="../../reference/db/#fastapi_toolsets.db.cleanup_tables"><code>cleanup_tables</code></a> truncates all tables:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-6-1"><a id="__codelineno-6-1" name="__codelineno-6-1" href="#__codelineno-6-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">cleanup_tables</span>
</span><span id="__span-6-2"><a id="__codelineno-6-2" name="__codelineno-6-2" href="#__codelineno-6-2"></a>
</span><span id="__span-6-3"><a id="__codelineno-6-3" name="__codelineno-6-3" href="#__codelineno-6-3"></a><span class="nd">@pytest</span><span class="o">.</span><span class="n">fixture</span><span class="p">(</span><span class="n">autouse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="__span-6-4"><a id="__codelineno-6-4" name="__codelineno-6-4" href="#__codelineno-6-4"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">clean</span><span class="p">(</span><span class="n">db_session</span><span class="p">):</span>
</span><span id="__span-6-5"><a id="__codelineno-6-5" name="__codelineno-6-5" href="#__codelineno-6-5"></a> <span class="k">yield</span>
</span><span id="__span-6-6"><a id="__codelineno-6-6" name="__codelineno-6-6" href="#__codelineno-6-6"></a> <span class="k">await</span> <span class="n">cleanup_tables</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">db_session</span><span class="p">,</span> <span class="n">base</span><span class="o">=</span><span class="n">Base</span><span class="p">)</span>
<p><a href="../../reference/db/#fastapi_toolsets.db.testing.cleanup_tables"><code>cleanup_tables</code></a> (in <code>fastapi_toolsets.db.testing</code>) truncates all tables:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-10-1"><a id="__codelineno-10-1" name="__codelineno-10-1" href="#__codelineno-10-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db.testing</span><span class="w"> </span><span class="kn">import</span> <span class="n">cleanup_tables</span>
</span><span id="__span-10-2"><a id="__codelineno-10-2" name="__codelineno-10-2" href="#__codelineno-10-2"></a>
</span><span id="__span-10-3"><a id="__codelineno-10-3" name="__codelineno-10-3" href="#__codelineno-10-3"></a><span class="nd">@pytest</span><span class="o">.</span><span class="n">fixture</span><span class="p">(</span><span class="n">autouse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="__span-10-4"><a id="__codelineno-10-4" name="__codelineno-10-4" href="#__codelineno-10-4"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">clean</span><span class="p">(</span><span class="n">db_session</span><span class="p">):</span>
</span><span id="__span-10-5"><a id="__codelineno-10-5" name="__codelineno-10-5" href="#__codelineno-10-5"></a> <span class="k">yield</span>
</span><span id="__span-10-6"><a id="__codelineno-10-6" name="__codelineno-10-6" href="#__codelineno-10-6"></a> <span class="k">await</span> <span class="n">cleanup_tables</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">db_session</span><span class="p">,</span> <span class="n">base</span><span class="o">=</span><span class="n">Base</span><span class="p">)</span>
</span></code></pre></div>
<h2 id="many-to-many-helpers">Many-to-Many helpers<a class="headerlink" href="#many-to-many-helpers" title="Permanent link">&para;</a></h2>
<p>SQLAlchemy's ORM collection API triggers lazy-loads when you append to a relationship inside a savepoint (e.g. inside <code>lock_tables</code> or a nested <code>get_transaction</code>). The three <code>m2m_*</code> helpers bypass the ORM collection entirely and issue direct SQL against the association table.</p>
<h3 id="m2m_add-insert-associations"><code>m2m_add</code> insert associations<a class="headerlink" href="#m2m_add-insert-associations" title="Permanent link">&para;</a></h3>
<p><a href="../../reference/db/#fastapi_toolsets.db.m2m_add"><code>m2m_add</code></a> inserts one or more rows into a secondary table without touching the ORM collection:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-7-1"><a id="__codelineno-7-1" name="__codelineno-7-1" href="#__codelineno-7-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">lock_tables</span><span class="p">,</span> <span class="n">m2m_add</span>
</span><span id="__span-7-2"><a id="__codelineno-7-2" name="__codelineno-7-2" href="#__codelineno-7-2"></a>
</span><span id="__span-7-3"><a id="__codelineno-7-3" name="__codelineno-7-3" href="#__codelineno-7-3"></a><span class="k">async</span> <span class="k">with</span> <span class="n">lock_tables</span><span class="p">(</span><span class="n">session_maker</span><span class="p">,</span> <span class="p">[</span><span class="n">Tag</span><span class="p">])</span> <span class="k">as</span> <span class="n">session</span><span class="p">:</span>
</span><span id="__span-7-4"><a id="__codelineno-7-4" name="__codelineno-7-4" href="#__codelineno-7-4"></a> <span class="n">tag</span> <span class="o">=</span> <span class="k">await</span> <span class="n">TagCrud</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">TagCreate</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">&quot;python&quot;</span><span class="p">))</span>
</span><span id="__span-7-5"><a id="__codelineno-7-5" name="__codelineno-7-5" href="#__codelineno-7-5"></a> <span class="k">await</span> <span class="n">m2m_add</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">post</span><span class="p">,</span> <span class="n">Post</span><span class="o">.</span><span class="n">tags</span><span class="p">,</span> <span class="n">tag</span><span class="p">)</span>
<p>The three <code>m2m_*</code> helpers modify a many-to-many association table with direct SQL, without loading the ORM collection.</p>
<h3 id="m2m_add-insert-associations"><code>m2m_add</code>: insert associations<a class="headerlink" href="#m2m_add-insert-associations" title="Permanent link">&para;</a></h3>
<p><a href="../../reference/db/#fastapi_toolsets.db.m2m_add"><code>m2m_add</code></a> inserts one or more rows into a secondary table:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-11-1"><a id="__codelineno-11-1" name="__codelineno-11-1" href="#__codelineno-11-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">m2m_add</span>
</span><span id="__span-11-2"><a id="__codelineno-11-2" name="__codelineno-11-2" href="#__codelineno-11-2"></a>
</span><span id="__span-11-3"><a id="__codelineno-11-3" name="__codelineno-11-3" href="#__codelineno-11-3"></a><span class="k">async</span> <span class="k">with</span> <span class="n">db</span><span class="o">.</span><span class="n">lock_tables</span><span class="p">([</span><span class="n">Tag</span><span class="p">])</span> <span class="k">as</span> <span class="n">session</span><span class="p">:</span>
</span><span id="__span-11-4"><a id="__codelineno-11-4" name="__codelineno-11-4" href="#__codelineno-11-4"></a> <span class="n">tag</span> <span class="o">=</span> <span class="k">await</span> <span class="n">TagCrud</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">TagCreate</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">&quot;python&quot;</span><span class="p">))</span>
</span><span id="__span-11-5"><a id="__codelineno-11-5" name="__codelineno-11-5" href="#__codelineno-11-5"></a> <span class="k">await</span> <span class="n">m2m_add</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">post</span><span class="p">,</span> <span class="n">Post</span><span class="o">.</span><span class="n">tags</span><span class="p">,</span> <span class="n">tag</span><span class="p">)</span>
</span></code></pre></div>
<p>Pass <code>ignore_conflicts=True</code> to silently skip associations that already exist:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-8-1"><a id="__codelineno-8-1" name="__codelineno-8-1" href="#__codelineno-8-1"></a><span class="k">await</span> <span class="n">m2m_add</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">post</span><span class="p">,</span> <span class="n">Post</span><span class="o">.</span><span class="n">tags</span><span class="p">,</span> <span class="n">tag</span><span class="p">,</span> <span class="n">ignore_conflicts</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<p>Pass <code>ignore_conflicts=True</code> to skip associations that already exist:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-12-1"><a id="__codelineno-12-1" name="__codelineno-12-1" href="#__codelineno-12-1"></a><span class="k">await</span> <span class="n">m2m_add</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">post</span><span class="p">,</span> <span class="n">Post</span><span class="o">.</span><span class="n">tags</span><span class="p">,</span> <span class="n">tag</span><span class="p">,</span> <span class="n">ignore_conflicts</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span></code></pre></div>
<h3 id="m2m_remove-delete-associations"><code>m2m_remove</code> delete associations<a class="headerlink" href="#m2m_remove-delete-associations" title="Permanent link">&para;</a></h3>
<h3 id="m2m_remove-delete-associations"><code>m2m_remove</code>: delete associations<a class="headerlink" href="#m2m_remove-delete-associations" title="Permanent link">&para;</a></h3>
<p><a href="../../reference/db/#fastapi_toolsets.db.m2m_remove"><code>m2m_remove</code></a> deletes specific association rows. Removing a non-existent association is a no-op:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-9-1"><a id="__codelineno-9-1" name="__codelineno-9-1" href="#__codelineno-9-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">get_transaction</span><span class="p">,</span> <span class="n">m2m_remove</span>
</span><span id="__span-9-2"><a id="__codelineno-9-2" name="__codelineno-9-2" href="#__codelineno-9-2"></a>
</span><span id="__span-9-3"><a id="__codelineno-9-3" name="__codelineno-9-3" href="#__codelineno-9-3"></a><span class="k">async</span> <span class="k">with</span> <span class="n">get_transaction</span><span class="p">(</span><span class="n">session</span><span class="p">):</span>
</span><span id="__span-9-4"><a id="__codelineno-9-4" name="__codelineno-9-4" href="#__codelineno-9-4"></a> <span class="k">await</span> <span class="n">m2m_remove</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">post</span><span class="p">,</span> <span class="n">Post</span><span class="o">.</span><span class="n">tags</span><span class="p">,</span> <span class="n">tag1</span><span class="p">,</span> <span class="n">tag2</span><span class="p">)</span>
<div class="language-python highlight"><pre><span></span><code><span id="__span-13-1"><a id="__codelineno-13-1" name="__codelineno-13-1" href="#__codelineno-13-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">m2m_remove</span><span class="p">,</span> <span class="n">transaction</span>
</span><span id="__span-13-2"><a id="__codelineno-13-2" name="__codelineno-13-2" href="#__codelineno-13-2"></a>
</span><span id="__span-13-3"><a id="__codelineno-13-3" name="__codelineno-13-3" href="#__codelineno-13-3"></a><span class="k">async</span> <span class="k">with</span> <span class="n">transaction</span><span class="p">(</span><span class="n">session</span><span class="p">):</span>
</span><span id="__span-13-4"><a id="__codelineno-13-4" name="__codelineno-13-4" href="#__codelineno-13-4"></a> <span class="k">await</span> <span class="n">m2m_remove</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">post</span><span class="p">,</span> <span class="n">Post</span><span class="o">.</span><span class="n">tags</span><span class="p">,</span> <span class="n">tag1</span><span class="p">,</span> <span class="n">tag2</span><span class="p">)</span>
</span></code></pre></div>
<h3 id="m2m_set-replace-the-full-set"><code>m2m_set</code> replace the full set<a class="headerlink" href="#m2m_set-replace-the-full-set" title="Permanent link">&para;</a></h3>
<p><a href="../../reference/db/#fastapi_toolsets.db.m2m_set"><code>m2m_set</code></a> atomically replaces all associations: it deletes every existing row for the owner instance then inserts the new set. Passing no related instances clears the association entirely:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-10-1"><a id="__codelineno-10-1" name="__codelineno-10-1" href="#__codelineno-10-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">get_transaction</span><span class="p">,</span> <span class="n">m2m_set</span>
</span><span id="__span-10-2"><a id="__codelineno-10-2" name="__codelineno-10-2" href="#__codelineno-10-2"></a>
</span><span id="__span-10-3"><a id="__codelineno-10-3" name="__codelineno-10-3" href="#__codelineno-10-3"></a><span class="c1"># Replace all tags</span>
</span><span id="__span-10-4"><a id="__codelineno-10-4" name="__codelineno-10-4" href="#__codelineno-10-4"></a><span class="k">async</span> <span class="k">with</span> <span class="n">get_transaction</span><span class="p">(</span><span class="n">session</span><span class="p">):</span>
</span><span id="__span-10-5"><a id="__codelineno-10-5" name="__codelineno-10-5" href="#__codelineno-10-5"></a> <span class="k">await</span> <span class="n">m2m_set</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">post</span><span class="p">,</span> <span class="n">Post</span><span class="o">.</span><span class="n">tags</span><span class="p">,</span> <span class="n">tag_a</span><span class="p">,</span> <span class="n">tag_b</span><span class="p">)</span>
</span><span id="__span-10-6"><a id="__codelineno-10-6" name="__codelineno-10-6" href="#__codelineno-10-6"></a>
</span><span id="__span-10-7"><a id="__codelineno-10-7" name="__codelineno-10-7" href="#__codelineno-10-7"></a><span class="c1"># Clear all tags</span>
</span><span id="__span-10-8"><a id="__codelineno-10-8" name="__codelineno-10-8" href="#__codelineno-10-8"></a><span class="k">async</span> <span class="k">with</span> <span class="n">get_transaction</span><span class="p">(</span><span class="n">session</span><span class="p">):</span>
</span><span id="__span-10-9"><a id="__codelineno-10-9" name="__codelineno-10-9" href="#__codelineno-10-9"></a> <span class="k">await</span> <span class="n">m2m_set</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">post</span><span class="p">,</span> <span class="n">Post</span><span class="o">.</span><span class="n">tags</span><span class="p">)</span>
<h3 id="m2m_set-replace-the-full-set"><code>m2m_set</code>: replace the full set<a class="headerlink" href="#m2m_set-replace-the-full-set" title="Permanent link">&para;</a></h3>
<p><a href="../../reference/db/#fastapi_toolsets.db.m2m_set"><code>m2m_set</code></a> replaces all associations: it deletes every existing row for the owner instance then inserts the new set. Passing no related instances clears the association:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-14-1"><a id="__codelineno-14-1" name="__codelineno-14-1" href="#__codelineno-14-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">m2m_set</span><span class="p">,</span> <span class="n">transaction</span>
</span><span id="__span-14-2"><a id="__codelineno-14-2" name="__codelineno-14-2" href="#__codelineno-14-2"></a>
</span><span id="__span-14-3"><a id="__codelineno-14-3" name="__codelineno-14-3" href="#__codelineno-14-3"></a><span class="c1"># Replace all tags</span>
</span><span id="__span-14-4"><a id="__codelineno-14-4" name="__codelineno-14-4" href="#__codelineno-14-4"></a><span class="k">async</span> <span class="k">with</span> <span class="n">transaction</span><span class="p">(</span><span class="n">session</span><span class="p">):</span>
</span><span id="__span-14-5"><a id="__codelineno-14-5" name="__codelineno-14-5" href="#__codelineno-14-5"></a> <span class="k">await</span> <span class="n">m2m_set</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">post</span><span class="p">,</span> <span class="n">Post</span><span class="o">.</span><span class="n">tags</span><span class="p">,</span> <span class="n">tag_a</span><span class="p">,</span> <span class="n">tag_b</span><span class="p">)</span>
</span><span id="__span-14-6"><a id="__codelineno-14-6" name="__codelineno-14-6" href="#__codelineno-14-6"></a>
</span><span id="__span-14-7"><a id="__codelineno-14-7" name="__codelineno-14-7" href="#__codelineno-14-7"></a><span class="c1"># Clear all tags</span>
</span><span id="__span-14-8"><a id="__codelineno-14-8" name="__codelineno-14-8" href="#__codelineno-14-8"></a><span class="k">async</span> <span class="k">with</span> <span class="n">transaction</span><span class="p">(</span><span class="n">session</span><span class="p">):</span>
</span><span id="__span-14-9"><a id="__codelineno-14-9" name="__codelineno-14-9" href="#__codelineno-14-9"></a> <span class="k">await</span> <span class="n">m2m_set</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">post</span><span class="p">,</span> <span class="n">Post</span><span class="o">.</span><span class="n">tags</span><span class="p">)</span>
</span></code></pre></div>
<p>All three helpers raise <code>TypeError</code> if the relationship attribute is not a Many-to-Many (i.e. has no secondary table).</p>
<hr />
@@ -2134,7 +2364,7 @@
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/module/dependencies/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/module/dependencies/">
<link rel="prev" href="../db/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -231,6 +231,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="../cli/" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item">
<a href="../../reference/cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -1647,6 +1723,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -1662,9 +1739,39 @@
<li class="md-path__item">
<a href="../cli/" class="md-path__link">
<span class="md-ellipsis">
Modules
</span>
@@ -1845,7 +1952,7 @@
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/module/exceptions/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/module/exceptions/">
<link rel="prev" href="../dependencies/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -231,6 +231,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="../cli/" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item">
<a href="../../reference/cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -1781,6 +1857,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -1796,9 +1873,39 @@
<li class="md-path__item">
<a href="../cli/" class="md-path__link">
<span class="md-ellipsis">
Modules
</span>
@@ -1894,6 +2001,16 @@
<td>422</td>
<td>Invalid Order Field</td>
</tr>
<tr>
<td><a href="../../reference/exceptions/#fastapi_toolsets.exceptions.exceptions.PoolExhaustedError"><code>PoolExhaustedError</code></a></td>
<td>503</td>
<td>Service Unavailable</td>
</tr>
<tr>
<td><a href="../../reference/exceptions/#fastapi_toolsets.exceptions.exceptions.LockTimeoutError"><code>LockTimeoutError</code></a></td>
<td>503</td>
<td>Service Unavailable</td>
</tr>
</tbody>
</table>
<h3 id="per-instance-overrides">Per-instance overrides<a class="headerlink" href="#per-instance-overrides" title="Permanent link">&para;</a></h3>
@@ -2086,7 +2203,7 @@
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/module/fixtures/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/module/fixtures/">
<link rel="prev" href="../exceptions/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -231,6 +231,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="../cli/" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item">
<a href="../../reference/cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -1857,6 +1933,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -1872,9 +1949,39 @@
<li class="md-path__item">
<a href="../cli/" class="md-path__link">
<span class="md-ellipsis">
Modules
</span>
@@ -2187,7 +2294,7 @@
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/module/logger/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/module/logger/">
<link rel="prev" href="../fixtures/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -231,6 +231,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="../cli/" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item">
<a href="../../reference/cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -1647,6 +1723,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -1662,9 +1739,39 @@
<li class="md-path__item">
<a href="../cli/" class="md-path__link">
<span class="md-ellipsis">
Modules
</span>
@@ -1823,7 +1930,7 @@
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/module/metrics/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/module/metrics/">
<link rel="prev" href="../logger/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -231,6 +231,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="../cli/" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item">
<a href="../../reference/cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -1769,6 +1845,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -1784,9 +1861,39 @@
<li class="md-path__item">
<a href="../cli/" class="md-path__link">
<span class="md-ellipsis">
Modules
</span>
@@ -2004,7 +2111,7 @@
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/module/models/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/module/models/">
<link rel="prev" href="../metrics/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -231,6 +231,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="../cli/" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item">
<a href="../../reference/cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -1891,6 +1967,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -1906,9 +1983,39 @@
<li class="md-path__item">
<a href="../cli/" class="md-path__link">
<span class="md-ellipsis">
Modules
</span>
@@ -2046,7 +2153,7 @@
</span></code></pre></div>
<div class="admonition info">
<p class="admonition-title">Callbacks fire on <code>session.commit()</code> only — not on savepoints.</p>
<p>Savepoints created by <a href="../db/"><code>get_transaction</code></a> or <code>begin_nested()</code> do <strong>not</strong>
<p>Savepoints created by <a href="../db/"><code>transaction</code></a> or <code>begin_nested()</code> do <strong>not</strong>
trigger callbacks. All events accumulated across flushes are dispatched once
when the outermost <code>commit()</code> is called.</p>
</div>
@@ -2261,7 +2368,7 @@ when the outermost <code>commit()</code> is called.</p>
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/module/pytest/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/module/pytest/">
<link rel="prev" href="../models/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -231,6 +231,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="../cli/" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item">
<a href="../../reference/cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -789,10 +865,10 @@
</li>
<li class="md-nav__item">
<a href="#overview" class="md-nav__link">
<a href="#async-client" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
Overview
Async client
</span>
</span>
</a>
@@ -800,24 +876,30 @@
</li>
<li class="md-nav__item">
<a href="#creating-an-async-client" class="md-nav__link">
<a href="#database-sessions" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
Creating an async client
Database sessions
</span>
</span>
</a>
<nav class="md-nav" aria-label="Database sessions">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#engine-and-session-options" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
Engine and session options
</span>
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#database-sessions-in-tests" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
Database sessions in tests
</span>
</span>
</a>
</ul>
</nav>
</li>
@@ -833,10 +915,10 @@
</li>
<li class="md-nav__item">
<a href="#cleaning-up-tables" class="md-nav__link">
<a href="#manual-table-cleanup" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
Cleaning up tables
Manual table cleanup
</span>
</span>
</a>
@@ -1632,10 +1714,10 @@
</li>
<li class="md-nav__item">
<a href="#overview" class="md-nav__link">
<a href="#async-client" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
Overview
Async client
</span>
</span>
</a>
@@ -1643,24 +1725,30 @@
</li>
<li class="md-nav__item">
<a href="#creating-an-async-client" class="md-nav__link">
<a href="#database-sessions" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
Creating an async client
Database sessions
</span>
</span>
</a>
<nav class="md-nav" aria-label="Database sessions">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#engine-and-session-options" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
Engine and session options
</span>
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#database-sessions-in-tests" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
Database sessions in tests
</span>
</span>
</a>
</ul>
</nav>
</li>
@@ -1676,10 +1764,10 @@
</li>
<li class="md-nav__item">
<a href="#cleaning-up-tables" class="md-nav__link">
<a href="#manual-table-cleanup" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
Cleaning up tables
Manual table cleanup
</span>
</span>
</a>
@@ -1713,6 +1801,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -1728,9 +1817,39 @@
<li class="md-path__item">
<a href="../cli/" class="md-path__link">
<span class="md-ellipsis">
Modules
</span>
@@ -1761,7 +1880,7 @@
<h1 id="pytest">Pytest<a class="headerlink" href="#pytest" title="Permanent link">&para;</a></h1>
<p>Testing helpers for FastAPI applications with async client, database sessions, and parallel worker support.</p>
<p>Testing helpers for FastAPI applications: async HTTP client, database sessions, and parallel worker support.</p>
<h2 id="installation">Installation<a class="headerlink" href="#installation" title="Permanent link">&para;</a></h2>
<div class="tabbed-set tabbed-alternate" data-tabs="1:2"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">uv</label><label for="__tabbed_1_2">pip</label></div>
<div class="tabbed-content">
@@ -1775,10 +1894,8 @@
</div>
</div>
</div>
<h2 id="overview">Overview<a class="headerlink" href="#overview" title="Permanent link">&para;</a></h2>
<p>The <code>pytest</code> module provides utilities for setting up async test clients, managing test database sessions, and supporting parallel test execution with <code>pytest-xdist</code>.</p>
<h2 id="creating-an-async-client">Creating an async client<a class="headerlink" href="#creating-an-async-client" title="Permanent link">&para;</a></h2>
<p>Use <a href="../../reference/pytest/#fastapi_toolsets.pytest.utils.create_async_client"><code>create_async_client</code></a> to get an <code>httpx.AsyncClient</code> configured for your FastAPI app:</p>
<h2 id="async-client">Async client<a class="headerlink" href="#async-client" title="Permanent link">&para;</a></h2>
<p>Use <a href="../../reference/pytest/#fastapi_toolsets.pytest.utils.create_async_client"><code>create_async_client</code></a> to get an <code>httpx.AsyncClient</code> bound to your FastAPI app:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-2-1"><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.pytest</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_async_client</span>
</span><span id="__span-2-2"><a id="__codelineno-2-2" name="__codelineno-2-2" href="#__codelineno-2-2"></a>
</span><span id="__span-2-3"><a id="__codelineno-2-3" name="__codelineno-2-3" href="#__codelineno-2-3"></a><span class="nd">@pytest</span><span class="o">.</span><span class="n">fixture</span>
@@ -1793,45 +1910,69 @@
</span><span id="__span-2-12"><a id="__codelineno-2-12" name="__codelineno-2-12" href="#__codelineno-2-12"></a> <span class="p">)</span> <span class="k">as</span> <span class="n">c</span><span class="p">:</span>
</span><span id="__span-2-13"><a id="__codelineno-2-13" name="__codelineno-2-13" href="#__codelineno-2-13"></a> <span class="k">yield</span> <span class="n">c</span>
</span></code></pre></div>
<h2 id="database-sessions-in-tests">Database sessions in tests<a class="headerlink" href="#database-sessions-in-tests" title="Permanent link">&para;</a></h2>
<p>Use <a href="../../reference/pytest/#fastapi_toolsets.pytest.utils.create_db_session"><code>create_db_session</code></a> to create an isolated <code>AsyncSession</code> for a test, combined with <a href="../../reference/pytest/#fastapi_toolsets.pytest.utils.create_worker_database"><code>create_worker_database</code></a> to set up a per-worker database:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-3-1"><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.pytest</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_worker_database</span><span class="p">,</span> <span class="n">create_db_session</span>
</span><span id="__span-3-2"><a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a>
</span><span id="__span-3-3"><a id="__codelineno-3-3" name="__codelineno-3-3" href="#__codelineno-3-3"></a><span class="nd">@pytest</span><span class="o">.</span><span class="n">fixture</span><span class="p">(</span><span class="n">scope</span><span class="o">=</span><span class="s2">&quot;session&quot;</span><span class="p">)</span>
</span><span id="__span-3-4"><a id="__codelineno-3-4" name="__codelineno-3-4" href="#__codelineno-3-4"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">worker_db_url</span><span class="p">():</span>
</span><span id="__span-3-5"><a id="__codelineno-3-5" name="__codelineno-3-5" href="#__codelineno-3-5"></a> <span class="k">async</span> <span class="k">with</span> <span class="n">create_worker_database</span><span class="p">(</span>
</span><span id="__span-3-6"><a id="__codelineno-3-6" name="__codelineno-3-6" href="#__codelineno-3-6"></a> <span class="n">database_url</span><span class="o">=</span><span class="nb">str</span><span class="p">(</span><span class="n">settings</span><span class="o">.</span><span class="n">SQLALCHEMY_DATABASE_URI</span><span class="p">)</span>
</span><span id="__span-3-7"><a id="__codelineno-3-7" name="__codelineno-3-7" href="#__codelineno-3-7"></a> <span class="p">)</span> <span class="k">as</span> <span class="n">url</span><span class="p">:</span>
</span><span id="__span-3-8"><a id="__codelineno-3-8" name="__codelineno-3-8" href="#__codelineno-3-8"></a> <span class="k">yield</span> <span class="n">url</span>
</span><span id="__span-3-9"><a id="__codelineno-3-9" name="__codelineno-3-9" href="#__codelineno-3-9"></a>
</span><span id="__span-3-10"><a id="__codelineno-3-10" name="__codelineno-3-10" href="#__codelineno-3-10"></a>
</span><span id="__span-3-11"><a id="__codelineno-3-11" name="__codelineno-3-11" href="#__codelineno-3-11"></a><span class="nd">@pytest</span><span class="o">.</span><span class="n">fixture</span>
</span><span id="__span-3-12"><a id="__codelineno-3-12" name="__codelineno-3-12" href="#__codelineno-3-12"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">db_session</span><span class="p">(</span><span class="n">worker_db_url</span><span class="p">):</span>
</span><span id="__span-3-13"><a id="__codelineno-3-13" name="__codelineno-3-13" href="#__codelineno-3-13"></a> <span class="k">async</span> <span class="k">with</span> <span class="n">create_db_session</span><span class="p">(</span>
</span><span id="__span-3-14"><a id="__codelineno-3-14" name="__codelineno-3-14" href="#__codelineno-3-14"></a> <span class="n">database_url</span><span class="o">=</span><span class="n">worker_db_url</span><span class="p">,</span> <span class="n">base</span><span class="o">=</span><span class="n">Base</span><span class="p">,</span> <span class="n">cleanup</span><span class="o">=</span><span class="kc">True</span>
</span><span id="__span-3-15"><a id="__codelineno-3-15" name="__codelineno-3-15" href="#__codelineno-3-15"></a> <span class="p">)</span> <span class="k">as</span> <span class="n">session</span><span class="p">:</span>
</span><span id="__span-3-16"><a id="__codelineno-3-16" name="__codelineno-3-16" href="#__codelineno-3-16"></a> <span class="k">yield</span> <span class="n">session</span>
<p>Any extra keyword arguments are forwarded to <code>httpx.AsyncClient</code>, so you can set default headers, authentication, timeouts, and more:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-3-1"><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a><span class="k">async</span> <span class="k">with</span> <span class="n">create_async_client</span><span class="p">(</span>
</span><span id="__span-3-2"><a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a> <span class="n">app</span><span class="o">=</span><span class="n">app</span><span class="p">,</span>
</span><span id="__span-3-3"><a id="__codelineno-3-3" name="__codelineno-3-3" href="#__codelineno-3-3"></a> <span class="n">headers</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;X-Api-Key&quot;</span><span class="p">:</span> <span class="s2">&quot;secret&quot;</span><span class="p">},</span>
</span><span id="__span-3-4"><a id="__codelineno-3-4" name="__codelineno-3-4" href="#__codelineno-3-4"></a> <span class="n">timeout</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span>
</span><span id="__span-3-5"><a id="__codelineno-3-5" name="__codelineno-3-5" href="#__codelineno-3-5"></a><span class="p">)</span> <span class="k">as</span> <span class="n">c</span><span class="p">:</span>
</span><span id="__span-3-6"><a id="__codelineno-3-6" name="__codelineno-3-6" href="#__codelineno-3-6"></a> <span class="o">...</span>
</span></code></pre></div>
<h2 id="database-sessions">Database sessions<a class="headerlink" href="#database-sessions" title="Permanent link">&para;</a></h2>
<p>Use <a href="../../reference/pytest/#fastapi_toolsets.pytest.utils.create_worker_database"><code>create_worker_database</code></a> + <a href="../../reference/pytest/#fastapi_toolsets.pytest.utils.create_db_session"><code>create_db_session</code></a> to get a fully isolated <code>AsyncSession</code> for each test:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-4-1"><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.pytest</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_worker_database</span><span class="p">,</span> <span class="n">create_db_session</span>
</span><span id="__span-4-2"><a id="__codelineno-4-2" name="__codelineno-4-2" href="#__codelineno-4-2"></a>
</span><span id="__span-4-3"><a id="__codelineno-4-3" name="__codelineno-4-3" href="#__codelineno-4-3"></a><span class="nd">@pytest</span><span class="o">.</span><span class="n">fixture</span><span class="p">(</span><span class="n">scope</span><span class="o">=</span><span class="s2">&quot;session&quot;</span><span class="p">)</span>
</span><span id="__span-4-4"><a id="__codelineno-4-4" name="__codelineno-4-4" href="#__codelineno-4-4"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">worker_db_url</span><span class="p">():</span>
</span><span id="__span-4-5"><a id="__codelineno-4-5" name="__codelineno-4-5" href="#__codelineno-4-5"></a> <span class="k">async</span> <span class="k">with</span> <span class="n">create_worker_database</span><span class="p">(</span>
</span><span id="__span-4-6"><a id="__codelineno-4-6" name="__codelineno-4-6" href="#__codelineno-4-6"></a> <span class="n">database_url</span><span class="o">=</span><span class="nb">str</span><span class="p">(</span><span class="n">settings</span><span class="o">.</span><span class="n">SQLALCHEMY_DATABASE_URI</span><span class="p">)</span>
</span><span id="__span-4-7"><a id="__codelineno-4-7" name="__codelineno-4-7" href="#__codelineno-4-7"></a> <span class="p">)</span> <span class="k">as</span> <span class="n">url</span><span class="p">:</span>
</span><span id="__span-4-8"><a id="__codelineno-4-8" name="__codelineno-4-8" href="#__codelineno-4-8"></a> <span class="k">yield</span> <span class="n">url</span>
</span><span id="__span-4-9"><a id="__codelineno-4-9" name="__codelineno-4-9" href="#__codelineno-4-9"></a>
</span><span id="__span-4-10"><a id="__codelineno-4-10" name="__codelineno-4-10" href="#__codelineno-4-10"></a>
</span><span id="__span-4-11"><a id="__codelineno-4-11" name="__codelineno-4-11" href="#__codelineno-4-11"></a><span class="nd">@pytest</span><span class="o">.</span><span class="n">fixture</span>
</span><span id="__span-4-12"><a id="__codelineno-4-12" name="__codelineno-4-12" href="#__codelineno-4-12"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">db_session</span><span class="p">(</span><span class="n">worker_db_url</span><span class="p">):</span>
</span><span id="__span-4-13"><a id="__codelineno-4-13" name="__codelineno-4-13" href="#__codelineno-4-13"></a> <span class="k">async</span> <span class="k">with</span> <span class="n">create_db_session</span><span class="p">(</span>
</span><span id="__span-4-14"><a id="__codelineno-4-14" name="__codelineno-4-14" href="#__codelineno-4-14"></a> <span class="n">database_url</span><span class="o">=</span><span class="n">worker_db_url</span><span class="p">,</span> <span class="n">base</span><span class="o">=</span><span class="n">Base</span><span class="p">,</span> <span class="n">cleanup</span><span class="o">=</span><span class="kc">True</span>
</span><span id="__span-4-15"><a id="__codelineno-4-15" name="__codelineno-4-15" href="#__codelineno-4-15"></a> <span class="p">)</span> <span class="k">as</span> <span class="n">session</span><span class="p">:</span>
</span><span id="__span-4-16"><a id="__codelineno-4-16" name="__codelineno-4-16" href="#__codelineno-4-16"></a> <span class="k">yield</span> <span class="n">session</span>
</span></code></pre></div>
<p><code>create_worker_database</code> connects without specifying a database (asyncpg falls back to the username), so the target test database does not need to exist beforehand.</p>
<div class="admonition info">
<p class="admonition-title">Info</p>
<p>In this example, the database is reset between each test using the argument <code>cleanup=True</code>.</p>
<p><code>cleanup=True</code> truncates all tables between tests via <code>TRUNCATE … RESTART IDENTITY CASCADE</code>, which is faster than dropping and recreating tables.</p>
</div>
<p>Use <a href="../../reference/pytest/#fastapi_toolsets.pytest.utils.worker_database_url"><code>worker_database_url</code></a> to derive the per-worker URL manually if needed:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-4-1"><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.pytest</span><span class="w"> </span><span class="kn">import</span> <span class="n">worker_database_url</span>
</span><span id="__span-4-2"><a id="__codelineno-4-2" name="__codelineno-4-2" href="#__codelineno-4-2"></a>
</span><span id="__span-4-3"><a id="__codelineno-4-3" name="__codelineno-4-3" href="#__codelineno-4-3"></a><span class="n">url</span> <span class="o">=</span> <span class="n">worker_database_url</span><span class="p">(</span><span class="s2">&quot;postgresql+asyncpg://user:pass@localhost/test_db&quot;</span><span class="p">,</span> <span class="n">default_test_db</span><span class="o">=</span><span class="s2">&quot;test&quot;</span><span class="p">)</span>
</span><span id="__span-4-4"><a id="__codelineno-4-4" name="__codelineno-4-4" href="#__codelineno-4-4"></a><span class="c1"># e.g. &quot;postgresql+asyncpg://user:pass@localhost/test_db_gw0&quot; under xdist</span>
<h3 id="engine-and-session-options">Engine and session options<a class="headerlink" href="#engine-and-session-options" title="Permanent link">&para;</a></h3>
<p>Pass <code>engine_kwargs</code> or <code>session_kwargs</code> to forward options to the underlying SQLAlchemy primitives:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-5-1"><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a><span class="k">async</span> <span class="k">with</span> <span class="n">create_db_session</span><span class="p">(</span>
</span><span id="__span-5-2"><a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a> <span class="n">database_url</span><span class="o">=</span><span class="n">worker_db_url</span><span class="p">,</span>
</span><span id="__span-5-3"><a id="__codelineno-5-3" name="__codelineno-5-3" href="#__codelineno-5-3"></a> <span class="n">base</span><span class="o">=</span><span class="n">Base</span><span class="p">,</span>
</span><span id="__span-5-4"><a id="__codelineno-5-4" name="__codelineno-5-4" href="#__codelineno-5-4"></a> <span class="n">engine_kwargs</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;pool_size&quot;</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">&quot;connect_args&quot;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&quot;timeout&quot;</span><span class="p">:</span> <span class="mi">10</span><span class="p">}},</span>
</span><span id="__span-5-5"><a id="__codelineno-5-5" name="__codelineno-5-5" href="#__codelineno-5-5"></a> <span class="n">session_kwargs</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;autoflush&quot;</span><span class="p">:</span> <span class="kc">False</span><span class="p">},</span>
</span><span id="__span-5-6"><a id="__codelineno-5-6" name="__codelineno-5-6" href="#__codelineno-5-6"></a><span class="p">)</span> <span class="k">as</span> <span class="n">session</span><span class="p">:</span>
</span><span id="__span-5-7"><a id="__codelineno-5-7" name="__codelineno-5-7" href="#__codelineno-5-7"></a> <span class="o">...</span>
</span></code></pre></div>
<h2 id="parallel-testing-with-pytest-xdist">Parallel testing with pytest-xdist<a class="headerlink" href="#parallel-testing-with-pytest-xdist" title="Permanent link">&para;</a></h2>
<p>The examples above are already compatible with parallel test execution with <code>pytest-xdist</code>.</p>
<h2 id="cleaning-up-tables">Cleaning up tables<a class="headerlink" href="#cleaning-up-tables" title="Permanent link">&para;</a></h2>
<p>If you want to manually clean up a database you can use <a href="../../reference/db/#fastapi_toolsets.db.cleanup_tables"><code>cleanup_tables</code></a>, this will truncate all tables between tests for fast isolation:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-5-1"><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.db</span><span class="w"> </span><span class="kn">import</span> <span class="n">cleanup_tables</span>
</span><span id="__span-5-2"><a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a>
</span><span id="__span-5-3"><a id="__codelineno-5-3" name="__codelineno-5-3" href="#__codelineno-5-3"></a><span class="nd">@pytest</span><span class="o">.</span><span class="n">fixture</span><span class="p">(</span><span class="n">autouse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="__span-5-4"><a id="__codelineno-5-4" name="__codelineno-5-4" href="#__codelineno-5-4"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">clean</span><span class="p">(</span><span class="n">db_session</span><span class="p">):</span>
</span><span id="__span-5-5"><a id="__codelineno-5-5" name="__codelineno-5-5" href="#__codelineno-5-5"></a> <span class="k">yield</span>
</span><span id="__span-5-6"><a id="__codelineno-5-6" name="__codelineno-5-6" href="#__codelineno-5-6"></a> <span class="k">await</span> <span class="n">cleanup_tables</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">db_session</span><span class="p">,</span> <span class="n">base</span><span class="o">=</span><span class="n">Base</span><span class="p">)</span>
<p>The fixtures above work with <code>pytest-xdist</code> out of the box. Each worker gets its own database named after the worker (e.g. <code>gw0</code>, <code>gw1</code>). Pass <code>prefix</code> to namespace the database (e.g. <code>prefix="myapp"</code><code>myapp_gw0</code>).</p>
<p>Use <a href="../../reference/pytest/#fastapi_toolsets.pytest.utils.worker_database_url"><code>worker_database_url</code></a> to derive the per-worker URL manually if needed:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-6-1"><a id="__codelineno-6-1" name="__codelineno-6-1" href="#__codelineno-6-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.pytest</span><span class="w"> </span><span class="kn">import</span> <span class="n">worker_database_url</span>
</span><span id="__span-6-2"><a id="__codelineno-6-2" name="__codelineno-6-2" href="#__codelineno-6-2"></a>
</span><span id="__span-6-3"><a id="__codelineno-6-3" name="__codelineno-6-3" href="#__codelineno-6-3"></a><span class="n">url</span> <span class="o">=</span> <span class="n">worker_database_url</span><span class="p">(</span><span class="s2">&quot;postgresql+asyncpg://user:pass@localhost/myapp&quot;</span><span class="p">,</span> <span class="n">default_test_db</span><span class="o">=</span><span class="s2">&quot;test&quot;</span><span class="p">)</span>
</span><span id="__span-6-4"><a id="__codelineno-6-4" name="__codelineno-6-4" href="#__codelineno-6-4"></a><span class="c1"># → &quot;postgresql+asyncpg://user:pass@localhost/gw0&quot; under xdist</span>
</span><span id="__span-6-5"><a id="__codelineno-6-5" name="__codelineno-6-5" href="#__codelineno-6-5"></a><span class="c1"># → &quot;postgresql+asyncpg://user:pass@localhost/test&quot; otherwise</span>
</span><span id="__span-6-6"><a id="__codelineno-6-6" name="__codelineno-6-6" href="#__codelineno-6-6"></a>
</span><span id="__span-6-7"><a id="__codelineno-6-7" name="__codelineno-6-7" href="#__codelineno-6-7"></a><span class="n">url</span> <span class="o">=</span> <span class="n">worker_database_url</span><span class="p">(</span><span class="s2">&quot;postgresql+asyncpg://user:pass@localhost/myapp&quot;</span><span class="p">,</span> <span class="n">default_test_db</span><span class="o">=</span><span class="s2">&quot;test&quot;</span><span class="p">,</span> <span class="n">prefix</span><span class="o">=</span><span class="s2">&quot;myapp&quot;</span><span class="p">)</span>
</span><span id="__span-6-8"><a id="__codelineno-6-8" name="__codelineno-6-8" href="#__codelineno-6-8"></a><span class="c1"># → &quot;postgresql+asyncpg://user:pass@localhost/myapp_gw0&quot; under xdist</span>
</span><span id="__span-6-9"><a id="__codelineno-6-9" name="__codelineno-6-9" href="#__codelineno-6-9"></a><span class="c1"># → &quot;postgresql+asyncpg://user:pass@localhost/myapp_test&quot; otherwise</span>
</span></code></pre></div>
<h2 id="manual-table-cleanup">Manual table cleanup<a class="headerlink" href="#manual-table-cleanup" title="Permanent link">&para;</a></h2>
<p><a href="../../reference/db/#fastapi_toolsets.db.testing.cleanup_tables"><code>cleanup_tables</code></a> truncates all tables in a single statement and can be called directly when you need more control:</p>
<div class="language-python highlight"><pre><span></span><code><span id="__span-7-1"><a id="__codelineno-7-1" name="__codelineno-7-1" href="#__codelineno-7-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.pytest</span><span class="w"> </span><span class="kn">import</span> <span class="n">cleanup_tables</span>
</span><span id="__span-7-2"><a id="__codelineno-7-2" name="__codelineno-7-2" href="#__codelineno-7-2"></a>
</span><span id="__span-7-3"><a id="__codelineno-7-3" name="__codelineno-7-3" href="#__codelineno-7-3"></a><span class="nd">@pytest</span><span class="o">.</span><span class="n">fixture</span><span class="p">(</span><span class="n">autouse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="__span-7-4"><a id="__codelineno-7-4" name="__codelineno-7-4" href="#__codelineno-7-4"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">clean</span><span class="p">(</span><span class="n">db_session</span><span class="p">):</span>
</span><span id="__span-7-5"><a id="__codelineno-7-5" name="__codelineno-7-5" href="#__codelineno-7-5"></a> <span class="k">yield</span>
</span><span id="__span-7-6"><a id="__codelineno-7-6" name="__codelineno-7-6" href="#__codelineno-7-6"></a> <span class="k">await</span> <span class="n">cleanup_tables</span><span class="p">(</span><span class="n">session</span><span class="o">=</span><span class="n">db_session</span><span class="p">,</span> <span class="n">base</span><span class="o">=</span><span class="n">Base</span><span class="p">)</span>
</span></code></pre></div>
<hr />
<p><a href="../../reference/pytest/"><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M7 7H5a2 2 0 0 0-2 2v8h2v-4h2v4h2V9a2 2 0 0 0-2-2m0 4H5V9h2m7-2h-4v10h2v-4h2a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2m0 4h-2V9h2m6 0v6h1v2h-4v-2h1V9h-1V7h4v2Z"/></svg></span> API Reference</a></p>
@@ -1941,7 +2082,7 @@
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/module/schemas/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/module/schemas/">
<link rel="prev" href="../pytest/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -231,6 +231,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="../cli/" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item">
<a href="../../reference/cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -1803,6 +1879,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -1818,9 +1895,39 @@
<li class="md-path__item">
<a href="../cli/" class="md-path__link">
<span class="md-ellipsis">
Modules
</span>
@@ -2087,7 +2194,7 @@
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/module/security/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/module/security/">
<link rel="prev" href="../schemas/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -231,6 +231,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="../cli/" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item">
<a href="../../reference/cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -2071,6 +2147,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -2086,9 +2163,39 @@
<li class="md-path__item">
<a href="../cli/" class="md-path__link">
<span class="md-ellipsis">
Modules
</span>
@@ -2481,7 +2588,7 @@ The <code>prefix</code> (for <code>BearerTokenAuth</code>), cookie name and <cod
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
BIN
View File
Binary file not shown.
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/reference/cli/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/reference/cli/">
<link rel="prev" href="../../module/security/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -229,6 +229,35 @@
<li class="md-tabs__item">
<a href="../../module/cli/" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="././" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -1713,6 +1789,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -1728,9 +1805,39 @@
<li class="md-path__item">
<a href="././" class="md-path__link">
<span class="md-ellipsis">
Reference
</span>
@@ -2172,7 +2279,7 @@
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/reference/crud/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/reference/crud/">
<link rel="prev" href="../cli/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -229,6 +229,35 @@
<li class="md-tabs__item">
<a href="../../module/cli/" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="../cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -2055,6 +2131,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -2070,9 +2147,39 @@
<li class="md-path__item">
<a href="../cli/" class="md-path__link">
<span class="md-ellipsis">
Reference
</span>
@@ -3210,7 +3317,7 @@ response envelope.</p>
</span><span id="__span-0-4"><a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a> <span class="o">*</span><span class="p">,</span>
</span><span id="__span-0-5"><a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a> <span class="n">joins</span><span class="p">:</span> <span class="n">JoinType</span> <span class="o">|</span> <span class="kc">None</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="__span-0-6"><a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a> <span class="n">outer_join</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-7"><a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a> <span class="n">with_for_update</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-7"><a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a> <span class="n">with_for_update</span><span class="p">:</span> <span class="n">_ForUpdateMode</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-8"><a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a> <span class="n">load_options</span><span class="p">:</span> <span class="n">Sequence</span><span class="p">[</span><span class="n">ExecutableOption</span><span class="p">]</span> <span class="o">|</span> <span class="kc">None</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="__span-0-9"><a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a> <span class="n">schema</span><span class="p">:</span> <span class="nb">type</span><span class="p">[</span><span class="n">SchemaType</span><span class="p">],</span>
</span><span id="__span-0-10"><a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Response</span><span class="p">[</span><span class="n">SchemaType</span><span class="p">]</span> <span class="o">|</span> <span class="kc">None</span>
@@ -3220,7 +3327,7 @@ response envelope.</p>
</span><span id="__span-0-4"><a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a> <span class="o">*</span><span class="p">,</span>
</span><span id="__span-0-5"><a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a> <span class="n">joins</span><span class="p">:</span> <span class="n">JoinType</span> <span class="o">|</span> <span class="kc">None</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="__span-0-6"><a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a> <span class="n">outer_join</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-7"><a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a> <span class="n">with_for_update</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-7"><a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a> <span class="n">with_for_update</span><span class="p">:</span> <span class="n">_ForUpdateMode</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-8"><a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a> <span class="n">load_options</span><span class="p">:</span> <span class="n">Sequence</span><span class="p">[</span><span class="n">ExecutableOption</span><span class="p">]</span> <span class="o">|</span> <span class="kc">None</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="__span-0-9"><a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a> <span class="n">schema</span><span class="p">:</span> <span class="kc">None</span> <span class="o">=</span> <span class="o">...</span><span class="p">,</span>
</span><span id="__span-0-10"><a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">ModelType</span> <span class="o">|</span> <span class="kc">None</span>
@@ -3312,7 +3419,7 @@ response envelope.</p>
<code>with_for_update</code>
</td>
<td>
<code><a class="autorefs autorefs-external" href="https://docs.python.org/3/library/functions.html#bool">bool</a></code>
<code><span title="fastapi_toolsets.crud.factory._ForUpdateMode">_ForUpdateMode</span></code>
</td>
<td>
<div class="doc-md-description">
@@ -3416,7 +3523,7 @@ the result is automatically wrapped in a <code>Response[schema]</code>.</p>
</span><span id="__span-0-4"><a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a> <span class="o">*</span><span class="p">,</span>
</span><span id="__span-0-5"><a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a> <span class="n">joins</span><span class="p">:</span> <span class="n">JoinType</span> <span class="o">|</span> <span class="kc">None</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="__span-0-6"><a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a> <span class="n">outer_join</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-7"><a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a> <span class="n">with_for_update</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-7"><a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a> <span class="n">with_for_update</span><span class="p">:</span> <span class="n">_ForUpdateMode</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-8"><a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a> <span class="n">load_options</span><span class="p">:</span> <span class="n">Sequence</span><span class="p">[</span><span class="n">ExecutableOption</span><span class="p">]</span> <span class="o">|</span> <span class="kc">None</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="__span-0-9"><a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a> <span class="n">schema</span><span class="p">:</span> <span class="nb">type</span><span class="p">[</span><span class="n">SchemaType</span><span class="p">],</span>
</span><span id="__span-0-10"><a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Response</span><span class="p">[</span><span class="n">SchemaType</span><span class="p">]</span>
@@ -3426,7 +3533,7 @@ the result is automatically wrapped in a <code>Response[schema]</code>.</p>
</span><span id="__span-0-4"><a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a> <span class="o">*</span><span class="p">,</span>
</span><span id="__span-0-5"><a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a> <span class="n">joins</span><span class="p">:</span> <span class="n">JoinType</span> <span class="o">|</span> <span class="kc">None</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="__span-0-6"><a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a> <span class="n">outer_join</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-7"><a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a> <span class="n">with_for_update</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-7"><a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a> <span class="n">with_for_update</span><span class="p">:</span> <span class="n">_ForUpdateMode</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-8"><a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a> <span class="n">load_options</span><span class="p">:</span> <span class="n">Sequence</span><span class="p">[</span><span class="n">ExecutableOption</span><span class="p">]</span> <span class="o">|</span> <span class="kc">None</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="__span-0-9"><a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a> <span class="n">schema</span><span class="p">:</span> <span class="kc">None</span> <span class="o">=</span> <span class="o">...</span><span class="p">,</span>
</span><span id="__span-0-10"><a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">ModelType</span>
@@ -3518,7 +3625,7 @@ the result is automatically wrapped in a <code>Response[schema]</code>.</p>
<code>with_for_update</code>
</td>
<td>
<code><a class="autorefs autorefs-external" href="https://docs.python.org/3/library/functions.html#bool">bool</a></code>
<code><span title="fastapi_toolsets.crud.factory._ForUpdateMode">_ForUpdateMode</span></code>
</td>
<td>
<div class="doc-md-description">
@@ -3630,7 +3737,7 @@ the result is automatically wrapped in a <code>Response[schema]</code>.</p>
<h3 id="fastapi_toolsets.crud.factory.AsyncCrud.get_multi" class="doc doc-heading">
<code class="highlight language-python"><span class="n">get_multi</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">filters</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">joins</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">outer_join</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">load_options</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">order_by</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">limit</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">offset</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span></code>
<code class="highlight language-python"><span class="n">get_multi</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">filters</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">joins</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">outer_join</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">with_for_update</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">load_options</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">order_by</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">limit</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">offset</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span></code>
<span class="doc doc-labels">
<small class="doc doc-label doc-label-async"><code>async</code></small>
@@ -3720,6 +3827,24 @@ the result is automatically wrapped in a <code>Response[schema]</code>.</p>
<code>False</code>
</td>
</tr>
<tr class="doc-section-item">
<td>
<code>with_for_update</code>
</td>
<td>
<code><span title="fastapi_toolsets.crud.factory._ForUpdateMode">_ForUpdateMode</span></code>
</td>
<td>
<div class="doc-md-description">
<p>Lock rows for update. <code>True</code> for plain <code>FOR UPDATE</code>,
<code>"nowait"</code> for <code>FOR UPDATE NOWAIT</code>, <code>"skip_locked"</code> for
<code>FOR UPDATE SKIP LOCKED</code>.</p>
</div>
</td>
<td>
<code>False</code>
</td>
</tr>
<tr class="doc-section-item">
<td>
<code>load_options</code>
@@ -3834,7 +3959,7 @@ the result is automatically wrapped in a <code>Response[schema]</code>.</p>
</span><span id="__span-0-4"><a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a> <span class="o">*</span><span class="p">,</span>
</span><span id="__span-0-5"><a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a> <span class="n">joins</span><span class="p">:</span> <span class="n">JoinType</span> <span class="o">|</span> <span class="kc">None</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="__span-0-6"><a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a> <span class="n">outer_join</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-7"><a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a> <span class="n">with_for_update</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-7"><a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a> <span class="n">with_for_update</span><span class="p">:</span> <span class="n">_ForUpdateMode</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-8"><a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a> <span class="n">load_options</span><span class="p">:</span> <span class="n">Sequence</span><span class="p">[</span><span class="n">ExecutableOption</span><span class="p">]</span> <span class="o">|</span> <span class="kc">None</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="__span-0-9"><a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a> <span class="n">schema</span><span class="p">:</span> <span class="nb">type</span><span class="p">[</span><span class="n">SchemaType</span><span class="p">],</span>
</span><span id="__span-0-10"><a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Response</span><span class="p">[</span><span class="n">SchemaType</span><span class="p">]</span> <span class="o">|</span> <span class="kc">None</span>
@@ -3844,7 +3969,7 @@ the result is automatically wrapped in a <code>Response[schema]</code>.</p>
</span><span id="__span-0-4"><a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a> <span class="o">*</span><span class="p">,</span>
</span><span id="__span-0-5"><a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a> <span class="n">joins</span><span class="p">:</span> <span class="n">JoinType</span> <span class="o">|</span> <span class="kc">None</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="__span-0-6"><a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a> <span class="n">outer_join</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-7"><a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a> <span class="n">with_for_update</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-7"><a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a> <span class="n">with_for_update</span><span class="p">:</span> <span class="n">_ForUpdateMode</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-8"><a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a> <span class="n">load_options</span><span class="p">:</span> <span class="n">Sequence</span><span class="p">[</span><span class="n">ExecutableOption</span><span class="p">]</span> <span class="o">|</span> <span class="kc">None</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
</span><span id="__span-0-9"><a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a> <span class="n">schema</span><span class="p">:</span> <span class="kc">None</span> <span class="o">=</span> <span class="o">...</span><span class="p">,</span>
</span><span id="__span-0-10"><a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">ModelType</span> <span class="o">|</span> <span class="kc">None</span>
@@ -3939,7 +4064,7 @@ matches the filters.</p>
<code>with_for_update</code>
</td>
<td>
<code><a class="autorefs autorefs-external" href="https://docs.python.org/3/library/functions.html#bool">bool</a></code>
<code><span title="fastapi_toolsets.crud.factory._ForUpdateMode">_ForUpdateMode</span></code>
</td>
<td>
<div class="doc-md-description">
@@ -5315,7 +5440,7 @@ field. Scalar → equality, list → IN clause. Raises
<h3 id="fastapi_toolsets.crud.factory.AsyncCrud.update" class="doc doc-heading">
<code class="highlight language-python"><span class="n">update</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">obj</span><span class="p">,</span> <span class="n">filters</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">exclude_unset</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">exclude_none</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span></code>
<code class="highlight language-python"><span class="n">update</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">obj</span><span class="p">,</span> <span class="n">filters</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">exclude_unset</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">exclude_none</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">with_for_update</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span></code>
<span class="doc doc-labels">
<small class="doc doc-label doc-label-async"><code>async</code></small>
@@ -5331,8 +5456,9 @@ field. Scalar → equality, list → IN clause. Raises
</span><span id="__span-0-5"><a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a> <span class="o">*</span><span class="p">,</span>
</span><span id="__span-0-6"><a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a> <span class="n">exclude_unset</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">True</span><span class="p">,</span>
</span><span id="__span-0-7"><a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a> <span class="n">exclude_none</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-8"><a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a> <span class="n">schema</span><span class="p">:</span> <span class="nb">type</span><span class="p">[</span><span class="n">SchemaType</span><span class="p">],</span>
</span><span id="__span-0-9"><a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Response</span><span class="p">[</span><span class="n">SchemaType</span><span class="p">]</span>
</span><span id="__span-0-8"><a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a> <span class="n">with_for_update</span><span class="p">:</span> <span class="n">_ForUpdateMode</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-9"><a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a> <span class="n">schema</span><span class="p">:</span> <span class="nb">type</span><span class="p">[</span><span class="n">SchemaType</span><span class="p">],</span>
</span><span id="__span-0-10"><a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Response</span><span class="p">[</span><span class="n">SchemaType</span><span class="p">]</span>
</span></code></pre></div><div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">update</span><span class="p">(</span>
</span><span id="__span-0-2"><a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a> <span class="n">session</span><span class="p">:</span> <span class="n">AsyncSession</span><span class="p">,</span>
</span><span id="__span-0-3"><a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a> <span class="n">obj</span><span class="p">:</span> <span class="n">BaseModel</span><span class="p">,</span>
@@ -5340,8 +5466,9 @@ field. Scalar → equality, list → IN clause. Raises
</span><span id="__span-0-5"><a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a> <span class="o">*</span><span class="p">,</span>
</span><span id="__span-0-6"><a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a> <span class="n">exclude_unset</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">True</span><span class="p">,</span>
</span><span id="__span-0-7"><a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a> <span class="n">exclude_none</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-8"><a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a> <span class="n">schema</span><span class="p">:</span> <span class="kc">None</span> <span class="o">=</span> <span class="o">...</span><span class="p">,</span>
</span><span id="__span-0-9"><a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">ModelType</span>
</span><span id="__span-0-8"><a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a> <span class="n">with_for_update</span><span class="p">:</span> <span class="n">_ForUpdateMode</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-9"><a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a> <span class="n">schema</span><span class="p">:</span> <span class="kc">None</span> <span class="o">=</span> <span class="o">...</span><span class="p">,</span>
</span><span id="__span-0-10"><a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">ModelType</span>
</span></code></pre></div> </div>
@@ -5441,6 +5568,24 @@ field. Scalar → equality, list → IN clause. Raises
<code>False</code>
</td>
</tr>
<tr class="doc-section-item">
<td>
<code>with_for_update</code>
</td>
<td>
<code><span title="fastapi_toolsets.crud.factory._ForUpdateMode">_ForUpdateMode</span></code>
</td>
<td>
<div class="doc-md-description">
<p>Lock the row before updating. <code>True</code> for plain
<code>FOR UPDATE</code>, <code>"nowait"</code> for <code>FOR UPDATE NOWAIT</code>,
<code>"skip_locked"</code> for <code>FOR UPDATE SKIP LOCKED</code>.</p>
</div>
</td>
<td>
<code>False</code>
</td>
</tr>
<tr class="doc-section-item">
<td>
<code>schema</code>
@@ -6430,7 +6575,7 @@ Must match one of the resolved search field keys.</p>
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
File diff suppressed because it is too large Load Diff
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/reference/dependencies/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/reference/dependencies/">
<link rel="prev" href="../db/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -229,6 +229,35 @@
<li class="md-tabs__item">
<a href="../../module/cli/" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="../cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -1625,6 +1701,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -1640,9 +1717,39 @@
<li class="md-path__item">
<a href="../cli/" class="md-path__link">
<span class="md-ellipsis">
Reference
</span>
@@ -2094,7 +2201,7 @@
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/reference/exceptions/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/reference/exceptions/">
<link rel="prev" href="../dependencies/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -229,6 +229,35 @@
<li class="md-tabs__item">
<a href="../../module/cli/" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="../cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -1299,6 +1375,62 @@
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#fastapi_toolsets.exceptions.exceptions.PoolExhaustedError" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
PoolExhaustedError
</span>
</span>
</a>
<nav class="md-nav" aria-label="PoolExhaustedError">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#fastapi_toolsets.exceptions.exceptions.PoolExhaustedError.__init__" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
__init__
</span>
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#fastapi_toolsets.exceptions.exceptions.LockTimeoutError" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
LockTimeoutError
</span>
</span>
</a>
<nav class="md-nav" aria-label="LockTimeoutError">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#fastapi_toolsets.exceptions.exceptions.LockTimeoutError.__init__" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
__init__
</span>
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
@@ -2078,6 +2210,62 @@
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#fastapi_toolsets.exceptions.exceptions.PoolExhaustedError" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
PoolExhaustedError
</span>
</span>
</a>
<nav class="md-nav" aria-label="PoolExhaustedError">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#fastapi_toolsets.exceptions.exceptions.PoolExhaustedError.__init__" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
__init__
</span>
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#fastapi_toolsets.exceptions.exceptions.LockTimeoutError" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
LockTimeoutError
</span>
</span>
</a>
<nav class="md-nav" aria-label="LockTimeoutError">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#fastapi_toolsets.exceptions.exceptions.LockTimeoutError.__init__" class="md-nav__link">
<span class="md-ellipsis">
<span class="md-typeset">
__init__
</span>
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
@@ -2129,6 +2317,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -2144,9 +2333,39 @@
<li class="md-path__item">
<a href="../cli/" class="md-path__link">
<span class="md-ellipsis">
Reference
</span>
@@ -2189,9 +2408,11 @@
</span><span id="__span-0-8"><a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a> <span class="n">InvalidSearchColumnError</span><span class="p">,</span>
</span><span id="__span-0-9"><a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a> <span class="n">InvalidFacetFilterError</span><span class="p">,</span>
</span><span id="__span-0-10"><a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a> <span class="n">InvalidOrderFieldError</span><span class="p">,</span>
</span><span id="__span-0-11"><a id="__codelineno-0-11" name="__codelineno-0-11" href="#__codelineno-0-11"></a> <span class="n">generate_error_responses</span><span class="p">,</span>
</span><span id="__span-0-12"><a id="__codelineno-0-12" name="__codelineno-0-12" href="#__codelineno-0-12"></a> <span class="n">init_exceptions_handlers</span><span class="p">,</span>
</span><span id="__span-0-13"><a id="__codelineno-0-13" name="__codelineno-0-13" href="#__codelineno-0-13"></a><span class="p">)</span>
</span><span id="__span-0-11"><a id="__codelineno-0-11" name="__codelineno-0-11" href="#__codelineno-0-11"></a> <span class="n">PoolExhaustedError</span><span class="p">,</span>
</span><span id="__span-0-12"><a id="__codelineno-0-12" name="__codelineno-0-12" href="#__codelineno-0-12"></a> <span class="n">LockTimeoutError</span><span class="p">,</span>
</span><span id="__span-0-13"><a id="__codelineno-0-13" name="__codelineno-0-13" href="#__codelineno-0-13"></a> <span class="n">generate_error_responses</span><span class="p">,</span>
</span><span id="__span-0-14"><a id="__codelineno-0-14" name="__codelineno-0-14" href="#__codelineno-0-14"></a> <span class="n">init_exceptions_handlers</span><span class="p">,</span>
</span><span id="__span-0-15"><a id="__codelineno-0-15" name="__codelineno-0-15" href="#__codelineno-0-15"></a><span class="p">)</span>
</span></code></pre></div>
@@ -3280,6 +3501,268 @@ HTTP response body.</p>
</div>
</div>
</div>
<div class="doc doc-object doc-class">
<h2 id="fastapi_toolsets.exceptions.exceptions.PoolExhaustedError" class="doc doc-heading">
<code>fastapi_toolsets.exceptions.exceptions.PoolExhaustedError</code>
<a href="#fastapi_toolsets.exceptions.exceptions.PoolExhaustedError" class="headerlink" title="Permanent link">&para;</a></h2>
<div class="doc doc-contents first">
<p class="doc doc-class-bases">
Bases: <code><a class="autorefs autorefs-internal" title="&lt;code&gt;fastapi_toolsets.exceptions.exceptions.ApiException&lt;/code&gt;" href="./#fastapi_toolsets.exceptions.exceptions.ApiException">ApiException</a></code></p>
<p>HTTP 503 - Database connection pool is exhausted.</p>
<div class="doc doc-children">
<div class="doc doc-object doc-function">
<h3 id="fastapi_toolsets.exceptions.exceptions.PoolExhaustedError.__init__" class="doc doc-heading">
<code class="highlight language-python"><span class="fm">__init__</span><span class="p">(</span><span class="n">detail</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span></code>
<a href="#fastapi_toolsets.exceptions.exceptions.PoolExhaustedError.__init__" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="doc doc-contents ">
<p>Initialize the exception.</p>
<p><span class="doc-section-title">Parameters:</span></p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr class="doc-section-item">
<td>
<code>detail</code>
</td>
<td>
<code><a class="autorefs autorefs-external" href="https://docs.python.org/3/library/stdtypes.html#str">str</a> | None</code>
</td>
<td>
<div class="doc-md-description">
<p>Optional human-readable message</p>
</div>
</td>
<td>
<code>None</code>
</td>
</tr>
<tr class="doc-section-item">
<td>
<code>desc</code>
</td>
<td>
<code><a class="autorefs autorefs-external" href="https://docs.python.org/3/library/stdtypes.html#str">str</a> | None</code>
</td>
<td>
<div class="doc-md-description">
<p>Optional per-instance override for the <code>description</code> field
in the HTTP response body.</p>
</div>
</td>
<td>
<code>None</code>
</td>
</tr>
<tr class="doc-section-item">
<td>
<code>data</code>
</td>
<td>
<code><a class="autorefs autorefs-external" title="typing.Any" href="https://docs.python.org/3/library/typing.html#typing.Any">Any</a></code>
</td>
<td>
<div class="doc-md-description">
<p>Optional per-instance override for the <code>data</code> field in the
HTTP response body.</p>
</div>
</td>
<td>
<code>None</code>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="doc doc-object doc-class">
<h2 id="fastapi_toolsets.exceptions.exceptions.LockTimeoutError" class="doc doc-heading">
<code>fastapi_toolsets.exceptions.exceptions.LockTimeoutError</code>
<a href="#fastapi_toolsets.exceptions.exceptions.LockTimeoutError" class="headerlink" title="Permanent link">&para;</a></h2>
<div class="doc doc-contents first">
<p class="doc doc-class-bases">
Bases: <code><a class="autorefs autorefs-internal" title="&lt;code&gt;fastapi_toolsets.exceptions.exceptions.ApiException&lt;/code&gt;" href="./#fastapi_toolsets.exceptions.exceptions.ApiException">ApiException</a></code></p>
<p>HTTP 503 - A database lock could not be acquired within the timeout.</p>
<div class="doc doc-children">
<div class="doc doc-object doc-function">
<h3 id="fastapi_toolsets.exceptions.exceptions.LockTimeoutError.__init__" class="doc doc-heading">
<code class="highlight language-python"><span class="fm">__init__</span><span class="p">(</span><span class="n">detail</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span></code>
<a href="#fastapi_toolsets.exceptions.exceptions.LockTimeoutError.__init__" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="doc doc-contents ">
<p>Initialize the exception.</p>
<p><span class="doc-section-title">Parameters:</span></p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr class="doc-section-item">
<td>
<code>detail</code>
</td>
<td>
<code><a class="autorefs autorefs-external" href="https://docs.python.org/3/library/stdtypes.html#str">str</a> | None</code>
</td>
<td>
<div class="doc-md-description">
<p>Optional human-readable message</p>
</div>
</td>
<td>
<code>None</code>
</td>
</tr>
<tr class="doc-section-item">
<td>
<code>desc</code>
</td>
<td>
<code><a class="autorefs autorefs-external" href="https://docs.python.org/3/library/stdtypes.html#str">str</a> | None</code>
</td>
<td>
<div class="doc-md-description">
<p>Optional per-instance override for the <code>description</code> field
in the HTTP response body.</p>
</div>
</td>
<td>
<code>None</code>
</td>
</tr>
<tr class="doc-section-item">
<td>
<code>data</code>
</td>
<td>
<code><a class="autorefs autorefs-external" title="typing.Any" href="https://docs.python.org/3/library/typing.html#typing.Any">Any</a></code>
</td>
<td>
<div class="doc-md-description">
<p>Optional per-instance override for the <code>data</code> field in the
HTTP response body.</p>
</div>
</td>
<td>
<code>None</code>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
@@ -3535,7 +4018,7 @@ HTTP response body.</p>
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/reference/fixtures/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/reference/fixtures/">
<link rel="prev" href="../exceptions/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -229,6 +229,35 @@
<li class="md-tabs__item">
<a href="../../module/cli/" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="../cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -2101,6 +2177,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -2116,9 +2193,39 @@
<li class="md-path__item">
<a href="../cli/" class="md-path__link">
<span class="md-ellipsis">
Reference
</span>
@@ -3647,7 +3754,7 @@ that returns a sequence of SQLAlchemy model instances.</p>
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/reference/logger/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/reference/logger/">
<link rel="prev" href="../fixtures/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -229,6 +229,35 @@
<li class="md-tabs__item">
<a href="../../module/cli/" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="../cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -1625,6 +1701,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -1640,9 +1717,39 @@
<li class="md-path__item">
<a href="../cli/" class="md-path__link">
<span class="md-ellipsis">
Reference
</span>
@@ -1993,7 +2100,7 @@ Pass <code>None</code> to get the root logger.</p>
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/reference/metrics/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/reference/metrics/">
<link rel="prev" href="../logger/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -229,6 +229,35 @@
<li class="md-tabs__item">
<a href="../../module/cli/" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="../cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -1791,6 +1867,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -1806,9 +1883,39 @@
<li class="md-path__item">
<a href="../cli/" class="md-path__link">
<span class="md-ellipsis">
Reference
</span>
@@ -2443,7 +2550,7 @@ If <code>False</code> (default), called once at init time.</p>
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/reference/models/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/reference/models/">
<link rel="prev" href="../metrics/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -229,6 +229,35 @@
<li class="md-tabs__item">
<a href="../../module/cli/" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="../cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -1757,6 +1833,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -1772,9 +1849,39 @@
<li class="md-path__item">
<a href="../cli/" class="md-path__link">
<span class="md-ellipsis">
Reference
</span>
@@ -2319,7 +2426,7 @@ Defaults to all event types.</p>
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/reference/pytest/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/reference/pytest/">
<link rel="prev" href="../models/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -229,6 +229,35 @@
<li class="md-tabs__item">
<a href="../../module/cli/" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="../cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -1691,6 +1767,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -1706,9 +1783,39 @@
<li class="md-path__item">
<a href="../cli/" class="md-path__link">
<span class="md-ellipsis">
Reference
</span>
@@ -1909,7 +2016,7 @@ Dependencies are resolved via pytest fixture dependencies.</p>
<h2 id="fastapi_toolsets.pytest.utils.create_async_client" class="doc doc-heading">
<code class="highlight language-python"><span class="n">fastapi_toolsets</span><span class="o">.</span><span class="n">pytest</span><span class="o">.</span><span class="n">utils</span><span class="o">.</span><span class="n">create_async_client</span><span class="p">(</span><span class="n">app</span><span class="p">,</span> <span class="n">base_url</span><span class="o">=</span><span class="s1">&#39;http://test&#39;</span><span class="p">,</span> <span class="n">dependency_overrides</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span></code>
<code class="highlight language-python"><span class="n">fastapi_toolsets</span><span class="o">.</span><span class="n">pytest</span><span class="o">.</span><span class="n">utils</span><span class="o">.</span><span class="n">create_async_client</span><span class="p">(</span><span class="n">app</span><span class="p">,</span> <span class="n">base_url</span><span class="o">=</span><span class="s1">&#39;http://test&#39;</span><span class="p">,</span> <span class="n">dependency_overrides</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span></code>
<span class="doc doc-labels">
<small class="doc doc-label doc-label-async"><code>async</code></small>
@@ -1984,6 +2091,24 @@ before yielding and cleaned up after.</p>
<code>None</code>
</td>
</tr>
<tr class="doc-section-item">
<td>
<code>**kwargs</code>
</td>
<td>
<code><a class="autorefs autorefs-external" title="typing.Any" href="https://docs.python.org/3/library/typing.html#typing.Any">Any</a></code>
</td>
<td>
<div class="doc-md-description">
<p>Additional keyword arguments forwarded to
:class:<code>httpx.AsyncClient</code> (e.g. <code>headers</code>, <code>cookies</code>,
<code>auth</code>, <code>timeout</code>).</p>
</div>
</td>
<td>
<code>{}</code>
</td>
</tr>
</tbody>
</table>
@@ -2059,7 +2184,7 @@ before yielding and cleaned up after.</p>
<h2 id="fastapi_toolsets.pytest.utils.create_db_session" class="doc doc-heading">
<code class="highlight language-python"><span class="n">fastapi_toolsets</span><span class="o">.</span><span class="n">pytest</span><span class="o">.</span><span class="n">utils</span><span class="o">.</span><span class="n">create_db_session</span><span class="p">(</span><span class="n">database_url</span><span class="p">,</span> <span class="n">base</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">echo</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">expire_on_commit</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">drop_tables</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">cleanup</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span></code>
<code class="highlight language-python"><span class="n">fastapi_toolsets</span><span class="o">.</span><span class="n">pytest</span><span class="o">.</span><span class="n">utils</span><span class="o">.</span><span class="n">create_db_session</span><span class="p">(</span><span class="n">database_url</span><span class="p">,</span> <span class="n">base</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">echo</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">expire_on_commit</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">drop_tables</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">cleanup</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">engine_kwargs</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">session_kwargs</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span></code>
<span class="doc doc-labels">
<small class="doc doc-label doc-label-async"><code>async</code></small>
@@ -2183,6 +2308,42 @@ Each call creates a fresh engine and session for test isolation.</p>
<code>False</code>
</td>
</tr>
<tr class="doc-section-item">
<td>
<code>engine_kwargs</code>
</td>
<td>
<code><a class="autorefs autorefs-external" href="https://docs.python.org/3/library/stdtypes.html#dict">dict</a>[<a class="autorefs autorefs-external" href="https://docs.python.org/3/library/stdtypes.html#str">str</a>, <a class="autorefs autorefs-external" title="typing.Any" href="https://docs.python.org/3/library/typing.html#typing.Any">Any</a>] | None</code>
</td>
<td>
<div class="doc-md-description">
<p>Additional keyword arguments forwarded to
:func:<code>sqlalchemy.ext.asyncio.create_async_engine</code>
(e.g. <code>pool_size</code>, <code>connect_args</code>).</p>
</div>
</td>
<td>
<code>None</code>
</td>
</tr>
<tr class="doc-section-item">
<td>
<code>session_kwargs</code>
</td>
<td>
<code><a class="autorefs autorefs-external" href="https://docs.python.org/3/library/stdtypes.html#dict">dict</a>[<a class="autorefs autorefs-external" href="https://docs.python.org/3/library/stdtypes.html#str">str</a>, <a class="autorefs autorefs-external" title="typing.Any" href="https://docs.python.org/3/library/typing.html#typing.Any">Any</a>] | None</code>
</td>
<td>
<div class="doc-md-description">
<p>Additional keyword arguments forwarded to
:class:<code>sqlalchemy.ext.asyncio.async_sessionmaker</code>
(e.g. <code>autoflush</code>, <code>class_</code>).</p>
</div>
</td>
<td>
<code>None</code>
</td>
</tr>
</tbody>
</table>
@@ -2239,7 +2400,7 @@ Each call creates a fresh engine and session for test isolation.</p>
<h2 id="fastapi_toolsets.pytest.utils.worker_database_url" class="doc doc-heading">
<code class="highlight language-python"><span class="n">fastapi_toolsets</span><span class="o">.</span><span class="n">pytest</span><span class="o">.</span><span class="n">utils</span><span class="o">.</span><span class="n">worker_database_url</span><span class="p">(</span><span class="n">database_url</span><span class="p">,</span> <span class="n">default_test_db</span><span class="p">)</span></code>
<code class="highlight language-python"><span class="n">fastapi_toolsets</span><span class="o">.</span><span class="n">pytest</span><span class="o">.</span><span class="n">utils</span><span class="o">.</span><span class="n">worker_database_url</span><span class="p">(</span><span class="n">database_url</span><span class="p">,</span> <span class="n">default_test_db</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">prefix</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span></code>
<a href="#fastapi_toolsets.pytest.utils.worker_database_url" class="headerlink" title="Permanent link">&para;</a></h2>
@@ -2247,9 +2408,10 @@ Each call creates a fresh engine and session for test isolation.</p>
<div class="doc doc-contents first">
<p>Derive a per-worker database URL for pytest-xdist parallel runs.</p>
<p>Appends <code>_{worker_name}</code> to the database name so each xdist worker
operates on its own database. When not running under xdist,
<code>_{default_test_db}</code> is appended instead.</p>
<p>Sets the database name to the worker name so each xdist worker operates
on its own database. When not running under xdist, <em>default_test_db</em> is
used instead. When <em>prefix</em> is provided, the name becomes
<code>{prefix}_{worker}</code>.</p>
<p>The worker name is read from the <code>PYTEST_XDIST_WORKER</code> environment
variable (set automatically by xdist in each worker process).</p>
@@ -2298,6 +2460,24 @@ variable (set automatically by xdist in each worker process).</p>
<em>required</em>
</td>
</tr>
<tr class="doc-section-item">
<td>
<code>prefix</code>
</td>
<td>
<code><a class="autorefs autorefs-external" href="https://docs.python.org/3/library/stdtypes.html#str">str</a> | None</code>
</td>
<td>
<div class="doc-md-description">
<p>Optional prefix prepended to the worker name
(e.g. <code>"test"</code><code>"test_gw0"</code>). Without it, the database
name is just the worker name (e.g. <code>"gw0"</code>).</p>
</div>
</td>
<td>
<code>None</code>
</td>
</tr>
</tbody>
</table>
@@ -2333,7 +2513,7 @@ variable (set automatically by xdist in each worker process).</p>
<h2 id="fastapi_toolsets.pytest.utils.create_worker_database" class="doc doc-heading">
<code class="highlight language-python"><span class="n">fastapi_toolsets</span><span class="o">.</span><span class="n">pytest</span><span class="o">.</span><span class="n">utils</span><span class="o">.</span><span class="n">create_worker_database</span><span class="p">(</span><span class="n">database_url</span><span class="p">,</span> <span class="n">default_test_db</span><span class="o">=</span><span class="s1">&#39;test_db&#39;</span><span class="p">)</span></code>
<code class="highlight language-python"><span class="n">fastapi_toolsets</span><span class="o">.</span><span class="n">pytest</span><span class="o">.</span><span class="n">utils</span><span class="o">.</span><span class="n">create_worker_database</span><span class="p">(</span><span class="n">database_url</span><span class="p">,</span> <span class="n">default_test_db</span><span class="o">=</span><span class="s1">&#39;test_db&#39;</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">prefix</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">server_url</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span></code>
<span class="doc doc-labels">
<small class="doc doc-label doc-label-async"><code>async</code></small>
@@ -2372,8 +2552,8 @@ name (e.g. <code>_gw0</code>). Otherwise it is suffixed with <em>default_test_d
</td>
<td>
<div class="doc-md-description">
<p>Original database connection URL (used as the server
connection and as the base for the worker database name).</p>
<p>Original database connection URL (used as the base for
the worker database name).</p>
</div>
</td>
<td>
@@ -2397,6 +2577,42 @@ connection and as the base for the worker database name).</p>
<code>&#39;test_db&#39;</code>
</td>
</tr>
<tr class="doc-section-item">
<td>
<code>prefix</code>
</td>
<td>
<code><a class="autorefs autorefs-external" href="https://docs.python.org/3/library/stdtypes.html#str">str</a> | None</code>
</td>
<td>
<div class="doc-md-description">
<p>Optional prefix prepended to the worker name
(e.g. <code>prefix="test"</code><code>"test_gw0"</code>). Without it, the
database name is just the worker name (e.g. <code>"gw0"</code>).</p>
</div>
</td>
<td>
<code>None</code>
</td>
</tr>
<tr class="doc-section-item">
<td>
<code>server_url</code>
</td>
<td>
<code><a class="autorefs autorefs-external" href="https://docs.python.org/3/library/stdtypes.html#str">str</a> | None</code>
</td>
<td>
<div class="doc-md-description">
<p>URL used for server-level DDL (must point to an existing
database on the same server). Defaults to <em>database_url</em> with the
database omitted, letting asyncpg fall back to the username.</p>
</div>
</td>
<td>
<code>None</code>
</td>
</tr>
</tbody>
</table>
@@ -2428,7 +2644,7 @@ connection and as the base for the worker database name).</p>
<summary>Example</summary>
<div class="language-python highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">fastapi_toolsets.pytest</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_worker_database</span><span class="p">,</span> <span class="n">create_db_session</span>
</span><span id="__span-0-2"><a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a>
</span><span id="__span-0-3"><a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a><span class="n">DATABASE_URL</span> <span class="o">=</span> <span class="s2">&quot;postgresql+asyncpg://postgres:postgres@localhost/test_db&quot;</span>
</span><span id="__span-0-3"><a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a><span class="n">DATABASE_URL</span> <span class="o">=</span> <span class="s2">&quot;postgresql+asyncpg://postgres:postgres@localhost/myapp&quot;</span>
</span><span id="__span-0-4"><a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a>
</span><span id="__span-0-5"><a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a><span class="nd">@pytest</span><span class="o">.</span><span class="n">fixture</span><span class="p">(</span><span class="n">scope</span><span class="o">=</span><span class="s2">&quot;session&quot;</span><span class="p">)</span>
</span><span id="__span-0-6"><a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">worker_db_url</span><span class="p">():</span>
@@ -2553,7 +2769,7 @@ connection and as the base for the worker database name).</p>
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/reference/schemas/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/reference/schemas/">
<link rel="prev" href="../pytest/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -229,6 +229,35 @@
<li class="md-tabs__item">
<a href="../../module/cli/" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="../cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -1879,6 +1955,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -1894,9 +1971,39 @@
<li class="md-path__item">
<a href="../cli/" class="md-path__link">
<span class="md-ellipsis">
Reference
</span>
@@ -2906,7 +3013,7 @@ by a unified <code>paginate()</code> endpoint.</p>
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
@@ -12,7 +12,7 @@
<meta name="author" content="d3vyce">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v4.0/reference/security/">
<link rel="canonical" href="https://fastapi-toolsets.d3vyce.fr/v5.0/reference/security/">
<link rel="prev" href="../schemas/">
@@ -25,7 +25,7 @@
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="zensical-0.0.40">
<meta name="generator" content="zensical-0.0.43">
@@ -229,6 +229,35 @@
<li class="md-tabs__item">
<a href="../../module/cli/" class="md-tabs__link">
@@ -250,6 +279,35 @@
<li class="md-tabs__item md-tabs__item--active">
<a href="../cli/" class="md-tabs__link">
@@ -269,6 +327,13 @@
<li class="md-tabs__item">
<a href="../../examples/pagination-search/" class="md-tabs__link">
@@ -287,6 +352,17 @@
<li class="md-tabs__item">
@@ -2279,6 +2355,7 @@
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
@@ -2294,9 +2371,39 @@
<li class="md-path__item">
<a href="../cli/" class="md-path__link">
<span class="md-ellipsis">
Reference
</span>
@@ -4069,7 +4176,7 @@ Do not forward arbitrary URLs to <code>RedirectResponse</code>.</p>
<script id="__config" type="application/json">{"annotate":null,"base":"../..","features":["announce.dismiss","content.action.view","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.tabs","navigation.top","navigation.tracking","search.highlight"],"search":"../../assets/javascripts/workers/search.e2d2d235.min.js","tags":null,"translations":{"clipboard.copied":"Copied to clipboard","clipboard.copy":"Copy to clipboard","search.result.more.one":"1 more on this page","search.result.more.other":"# more on this page","search.result.none":"No matching documents","search.result.one":"1 matching document","search.result.other":"# matching documents","search.result.placeholder":"Type to start searching","search.result.term.missing":"Missing","select.version":"Select version"},"version":{"alias":true,"default":"stable","provider":"mike"}}</script>
<script src="../../assets/javascripts/bundle.dbc0afdc.min.js"></script>
<script src="../../assets/javascripts/bundle.6e5f0216.min.js"></script>
</body>
+1
View File
File diff suppressed because one or more lines are too long
+90
View File
@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/module/cli/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/module/crud/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/module/db/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/module/dependencies/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/module/exceptions/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/module/fixtures/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/module/logger/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/module/metrics/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/module/models/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/module/pytest/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/module/schemas/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/module/security/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/reference/cli/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/reference/crud/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/reference/db/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/reference/dependencies/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/reference/exceptions/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/reference/fixtures/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/reference/logger/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/reference/metrics/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/reference/models/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/reference/pytest/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/reference/schemas/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/reference/security/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/examples/pagination-search/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/migration/v4/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/migration/v3/</loc>
</url>
<url>
<loc>https://fastapi-toolsets.d3vyce.fr/v5.0/migration/v2/</loc>
</url>
</urlset>
+4 -4
View File
@@ -1,14 +1,14 @@
[
{
"version": "v4.1",
"title": "v4.1",
"version": "v5.0",
"title": "v5.0",
"aliases": [
"stable"
]
},
{
"version": "v4.0",
"title": "v4.0",
"version": "v4.1",
"title": "v4.1",
"aliases": []
},
{