docs: collect refreshed mongo-ops wiki site (API-correct overhaul, v0.1.5)
This commit is contained in:
@@ -454,7 +454,7 @@
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
02 components
|
||||
Core Components
|
||||
|
||||
</span>
|
||||
|
||||
@@ -904,6 +904,8 @@
|
||||
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-nav__link md-nav__link--active" for="__toc">
|
||||
|
||||
@@ -936,6 +938,8 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-nav__title" for="__toc">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
@@ -944,9 +948,36 @@
|
||||
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#error-handling" class="md-nav__link">
|
||||
<a href="#library-raised-exceptions" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Error Handling
|
||||
📋 Library-Raised Exceptions
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#fastapi-mapping-example" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
🚀 FastAPI Mapping Example
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#tips" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
💡 Tips
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#related" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Related
|
||||
</span>
|
||||
</a>
|
||||
|
||||
@@ -998,33 +1029,145 @@
|
||||
|
||||
|
||||
|
||||
<h1>Error Handling</h1>
|
||||
|
||||
<h2 id="error-handling">Error Handling</h2>
|
||||
<div class="language-python highlight"><span class="filename">Python</span><pre><span></span><code><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">HTTPException</span>
|
||||
<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">pymongo.errors</span><span class="w"> </span><span class="kn">import</span> <span class="n">DuplicateKeyError</span>
|
||||
<a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a><span class="kn">from</span><span class="w"> </span><span class="nn">bson.errors</span><span class="w"> </span><span class="kn">import</span> <span class="n">InvalidId</span>
|
||||
<a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a>
|
||||
<a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a><span class="nd">@app</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="s2">"/users/"</span><span class="p">)</span>
|
||||
<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">create_user</span><span class="p">(</span><span class="n">user</span><span class="p">:</span> <span class="n">User</span><span class="p">):</span>
|
||||
<a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a> <span class="k">try</span><span class="p">:</span>
|
||||
<a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">user_repo</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">user</span><span class="p">)</span>
|
||||
<a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a> <span class="k">except</span> <span class="n">DuplicateKeyError</span><span class="p">:</span>
|
||||
<a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a> <span class="k">raise</span> <span class="n">HTTPException</span><span class="p">(</span><span class="n">status_code</span><span class="o">=</span><span class="mi">409</span><span class="p">,</span> <span class="n">detail</span><span class="o">=</span><span class="s2">"User already exists"</span><span class="p">)</span>
|
||||
<a id="__codelineno-0-11" name="__codelineno-0-11" href="#__codelineno-0-11"></a> <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||||
<a id="__codelineno-0-12" name="__codelineno-0-12" href="#__codelineno-0-12"></a> <span class="k">raise</span> <span class="n">HTTPException</span><span class="p">(</span><span class="n">status_code</span><span class="o">=</span><span class="mi">500</span><span class="p">,</span> <span class="n">detail</span><span class="o">=</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">))</span>
|
||||
<a id="__codelineno-0-13" name="__codelineno-0-13" href="#__codelineno-0-13"></a>
|
||||
<a id="__codelineno-0-14" name="__codelineno-0-14" href="#__codelineno-0-14"></a><span class="nd">@app</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"/users/</span><span class="si">{user_id}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<a id="__codelineno-0-15" name="__codelineno-0-15" href="#__codelineno-0-15"></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">user_id</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
|
||||
<a id="__codelineno-0-16" name="__codelineno-0-16" href="#__codelineno-0-16"></a> <span class="k">try</span><span class="p">:</span>
|
||||
<a id="__codelineno-0-17" name="__codelineno-0-17" href="#__codelineno-0-17"></a> <span class="n">user</span> <span class="o">=</span> <span class="k">await</span> <span class="n">user_repo</span><span class="o">.</span><span class="n">get_by_id</span><span class="p">(</span><span class="n">user_id</span><span class="p">)</span>
|
||||
<a id="__codelineno-0-18" name="__codelineno-0-18" href="#__codelineno-0-18"></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">user</span><span class="p">:</span>
|
||||
<a id="__codelineno-0-19" name="__codelineno-0-19" href="#__codelineno-0-19"></a> <span class="k">raise</span> <span class="n">HTTPException</span><span class="p">(</span><span class="n">status_code</span><span class="o">=</span><span class="mi">404</span><span class="p">,</span> <span class="n">detail</span><span class="o">=</span><span class="s2">"User not found"</span><span class="p">)</span>
|
||||
<a id="__codelineno-0-20" name="__codelineno-0-20" href="#__codelineno-0-20"></a> <span class="k">return</span> <span class="n">user</span>
|
||||
<a id="__codelineno-0-21" name="__codelineno-0-21" href="#__codelineno-0-21"></a> <span class="k">except</span> <span class="n">InvalidId</span><span class="p">:</span>
|
||||
<a id="__codelineno-0-22" name="__codelineno-0-22" href="#__codelineno-0-22"></a> <span class="k">raise</span> <span class="n">HTTPException</span><span class="p">(</span><span class="n">status_code</span><span class="o">=</span><span class="mi">400</span><span class="p">,</span> <span class="n">detail</span><span class="o">=</span><span class="s2">"Invalid user ID format"</span><span class="p">)</span>
|
||||
</code></pre></div>
|
||||
<h1 id="error-handling">Error Handling</h1>
|
||||
<p>What can raise, what it means, and how to map it in a FastAPI app.</p>
|
||||
<hr />
|
||||
<h2 id="library-raised-exceptions">📋 Library-Raised Exceptions</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Exception</th>
|
||||
<th>Source</th>
|
||||
<th>Meaning / fix</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>RuntimeError("Database not connected. Call connect() first.")</code></td>
|
||||
<td><code>get_database()</code> / <code>get_client()</code> and any repository constructed first</td>
|
||||
<td><code>MongoConnectionManager.connect()</code> hasn't run — wire the lifespan.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>RuntimeError("No cache backend registered. Call set_cache_backend() first.")</code></td>
|
||||
<td><code>ModelRegistry.initialize_cache()</code></td>
|
||||
<td>Call <code>set_cache_backend(backend)</code> before <code>initialize_cache()</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>KeyError("Model for collection '...' not registered")</code></td>
|
||||
<td><code>ModelRegistry.get_model()</code></td>
|
||||
<td>Collection was never <code>register</code>ed (or typo).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>ValueError("Cannot patch FK fields via patch(): ...")</code></td>
|
||||
<td><code>PopulatingRepository.patch()</code></td>
|
||||
<td><code>patch</code> must not touch populated ref fields — use <code>update()</code> with a model.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>ValueError("...contains embedded dict(s) — run repair script")</code></td>
|
||||
<td><code>_populate</code> on read</td>
|
||||
<td>A FK field holds an embedded document instead of an <code>ObjectId</code> — migrate the data.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>ValueError("...contains ObjectId — was populate skipped?")</code></td>
|
||||
<td><code>_depopulate</code> on write</td>
|
||||
<td>A populate-ruled field is still an <code>ObjectId</code> at depopulate time — the read must have populated it first.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>CircularReferenceError(collection, doc_id, path)</code></td>
|
||||
<td><code>PopulationEngine.populate</code></td>
|
||||
<td>A <code>(Class, id)</code> pair was revisited — raise <code>max_depth</code> or fix the graph.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>ImportError("redis package required ... mongo-ops[redis]")</code></td>
|
||||
<td><code>CacheConfig</code> / <code>RedisCacheBackend</code></td>
|
||||
<td>Missing <code>redis</code> extra.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>ValueError("redis_client required when backend='redis'")</code></td>
|
||||
<td><code>CacheConfig</code></td>
|
||||
<td><code>backend="redis"</code> without a client.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pymongo <code>DuplicateKeyError</code></td>
|
||||
<td>any insert/update</td>
|
||||
<td>Unique index violation (e.g., duplicate email).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>bson.errors.InvalidId</code></td>
|
||||
<td><code>ObjectId(...)</code> on a bad string</td>
|
||||
<td>Wrapped by <code>PyObjectId</code> model validation on API inputs.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<blockquote>
|
||||
<p><code>KeyError</code> for <code>ModelRegistry.get_model</code> and the <code>RuntimeError</code>/<code>ValueError</code> guards are <strong>by design</strong> — they fail loudly at startup or first call instead of misbehaving silently.</p>
|
||||
</blockquote>
|
||||
<hr />
|
||||
<h2 id="fastapi-mapping-example">🚀 FastAPI Mapping Example</h2>
|
||||
<div class="language-python highlight"><span class="filename">Python</span><pre><span></span><code><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">FastAPI</span><span class="p">,</span> <span class="n">HTTPException</span><span class="p">,</span> <span class="n">Request</span>
|
||||
<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.responses</span><span class="w"> </span><span class="kn">import</span> <span class="n">JSONResponse</span>
|
||||
<a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a><span class="kn">from</span><span class="w"> </span><span class="nn">bson.errors</span><span class="w"> </span><span class="kn">import</span> <span class="n">InvalidId</span>
|
||||
<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">pymongo.errors</span><span class="w"> </span><span class="kn">import</span> <span class="n">DuplicateKeyError</span>
|
||||
<a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a><span class="kn">from</span><span class="w"> </span><span class="nn">mongo_ops.cache</span><span class="w"> </span><span class="kn">import</span> <span class="n">CircularReferenceError</span>
|
||||
<a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a>
|
||||
<a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a>
|
||||
<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>
|
||||
<a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a>
|
||||
<a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a>
|
||||
<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">exception_handler</span><span class="p">(</span><span class="n">DuplicateKeyError</span><span class="p">)</span>
|
||||
<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">duplicate_key_handler</span><span class="p">(</span><span class="n">_</span><span class="p">:</span> <span class="n">Request</span><span class="p">,</span> <span class="n">__</span><span class="p">:</span> <span class="n">DuplicateKeyError</span><span class="p">)</span> <span class="o">-></span> <span class="n">JSONResponse</span><span class="p">:</span>
|
||||
<a id="__codelineno-0-13" name="__codelineno-0-13" href="#__codelineno-0-13"></a> <span class="k">return</span> <span class="n">JSONResponse</span><span class="p">(</span><span class="n">status_code</span><span class="o">=</span><span class="mi">409</span><span class="p">,</span> <span class="n">content</span><span class="o">=</span><span class="p">{</span><span class="s2">"detail"</span><span class="p">:</span> <span class="s2">"Resource already exists"</span><span class="p">})</span>
|
||||
<a id="__codelineno-0-14" name="__codelineno-0-14" href="#__codelineno-0-14"></a>
|
||||
<a id="__codelineno-0-15" name="__codelineno-0-15" href="#__codelineno-0-15"></a>
|
||||
<a id="__codelineno-0-16" name="__codelineno-0-16" href="#__codelineno-0-16"></a><span class="nd">@app</span><span class="o">.</span><span class="n">exception_handler</span><span class="p">(</span><span class="n">InvalidId</span><span class="p">)</span>
|
||||
<a id="__codelineno-0-17" name="__codelineno-0-17" href="#__codelineno-0-17"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">invalid_id_handler</span><span class="p">(</span><span class="n">_</span><span class="p">:</span> <span class="n">Request</span><span class="p">,</span> <span class="n">__</span><span class="p">:</span> <span class="n">InvalidId</span><span class="p">)</span> <span class="o">-></span> <span class="n">JSONResponse</span><span class="p">:</span>
|
||||
<a id="__codelineno-0-18" name="__codelineno-0-18" href="#__codelineno-0-18"></a> <span class="k">return</span> <span class="n">JSONResponse</span><span class="p">(</span><span class="n">status_code</span><span class="o">=</span><span class="mi">400</span><span class="p">,</span> <span class="n">content</span><span class="o">=</span><span class="p">{</span><span class="s2">"detail"</span><span class="p">:</span> <span class="s2">"Invalid ID format"</span><span class="p">})</span>
|
||||
<a id="__codelineno-0-19" name="__codelineno-0-19" href="#__codelineno-0-19"></a>
|
||||
<a id="__codelineno-0-20" name="__codelineno-0-20" href="#__codelineno-0-20"></a>
|
||||
<a id="__codelineno-0-21" name="__codelineno-0-21" href="#__codelineno-0-21"></a><span class="nd">@app</span><span class="o">.</span><span class="n">exception_handler</span><span class="p">(</span><span class="n">CircularReferenceError</span><span class="p">)</span>
|
||||
<a id="__codelineno-0-22" name="__codelineno-0-22" href="#__codelineno-0-22"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">circular_ref_handler</span><span class="p">(</span><span class="n">_</span><span class="p">:</span> <span class="n">Request</span><span class="p">,</span> <span class="n">exc</span><span class="p">:</span> <span class="n">CircularReferenceError</span><span class="p">)</span> <span class="o">-></span> <span class="n">JSONResponse</span><span class="p">:</span>
|
||||
<a id="__codelineno-0-23" name="__codelineno-0-23" href="#__codelineno-0-23"></a> <span class="k">return</span> <span class="n">JSONResponse</span><span class="p">(</span>
|
||||
<a id="__codelineno-0-24" name="__codelineno-0-24" href="#__codelineno-0-24"></a> <span class="n">status_code</span><span class="o">=</span><span class="mi">409</span><span class="p">,</span>
|
||||
<a id="__codelineno-0-25" name="__codelineno-0-25" href="#__codelineno-0-25"></a> <span class="n">content</span><span class="o">=</span><span class="p">{</span><span class="s2">"detail"</span><span class="p">:</span> <span class="sa">f</span><span class="s2">"Circular reference detected: </span><span class="si">{</span><span class="n">exc</span><span class="o">.</span><span class="n">path</span><span class="si">}</span><span class="s2">"</span><span class="p">},</span>
|
||||
<a id="__codelineno-0-26" name="__codelineno-0-26" href="#__codelineno-0-26"></a> <span class="p">)</span>
|
||||
<a id="__codelineno-0-27" name="__codelineno-0-27" href="#__codelineno-0-27"></a>
|
||||
<a id="__codelineno-0-28" name="__codelineno-0-28" href="#__codelineno-0-28"></a>
|
||||
<a id="__codelineno-0-29" name="__codelineno-0-29" href="#__codelineno-0-29"></a><span class="c1"># Or handle inline for route-specific responses:</span>
|
||||
<a id="__codelineno-0-30" name="__codelineno-0-30" href="#__codelineno-0-30"></a><span class="nd">@app</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="s2">"/users/"</span><span class="p">)</span>
|
||||
<a id="__codelineno-0-31" name="__codelineno-0-31" href="#__codelineno-0-31"></a><span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">create_user</span><span class="p">(</span><span class="n">user</span><span class="p">:</span> <span class="n">User</span><span class="p">,</span> <span class="n">repo</span><span class="o">=</span><span class="n">Depends</span><span class="p">(</span><span class="n">get_user_repository</span><span class="p">)):</span>
|
||||
<a id="__codelineno-0-32" name="__codelineno-0-32" href="#__codelineno-0-32"></a> <span class="k">try</span><span class="p">:</span>
|
||||
<a id="__codelineno-0-33" name="__codelineno-0-33" href="#__codelineno-0-33"></a> <span class="k">return</span> <span class="k">await</span> <span class="n">repo</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">user</span><span class="p">)</span>
|
||||
<a id="__codelineno-0-34" name="__codelineno-0-34" href="#__codelineno-0-34"></a> <span class="k">except</span> <span class="n">DuplicateKeyError</span><span class="p">:</span>
|
||||
<a id="__codelineno-0-35" name="__codelineno-0-35" href="#__codelineno-0-35"></a> <span class="k">raise</span> <span class="n">HTTPException</span><span class="p">(</span><span class="n">status_code</span><span class="o">=</span><span class="mi">409</span><span class="p">,</span> <span class="n">detail</span><span class="o">=</span><span class="s2">"User already exists"</span><span class="p">)</span>
|
||||
<a id="__codelineno-0-36" name="__codelineno-0-36" href="#__codelineno-0-36"></a> <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
|
||||
<a id="__codelineno-0-37" name="__codelineno-0-37" href="#__codelineno-0-37"></a> <span class="k">raise</span> <span class="n">HTTPException</span><span class="p">(</span><span class="n">status_code</span><span class="o">=</span><span class="mi">500</span><span class="p">,</span> <span class="n">detail</span><span class="o">=</span><span class="nb">str</span><span class="p">(</span><span class="n">exc</span><span class="p">))</span>
|
||||
<a id="__codelineno-0-38" name="__codelineno-0-38" href="#__codelineno-0-38"></a>
|
||||
<a id="__codelineno-0-39" name="__codelineno-0-39" href="#__codelineno-0-39"></a>
|
||||
<a id="__codelineno-0-40" name="__codelineno-0-40" href="#__codelineno-0-40"></a><span class="nd">@app</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"/users/</span><span class="si">{user_id}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<a id="__codelineno-0-41" name="__codelineno-0-41" href="#__codelineno-0-41"></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">user_id</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">repo</span><span class="o">=</span><span class="n">Depends</span><span class="p">(</span><span class="n">get_user_repository</span><span class="p">)):</span>
|
||||
<a id="__codelineno-0-42" name="__codelineno-0-42" href="#__codelineno-0-42"></a> <span class="k">try</span><span class="p">:</span>
|
||||
<a id="__codelineno-0-43" name="__codelineno-0-43" href="#__codelineno-0-43"></a> <span class="n">user</span> <span class="o">=</span> <span class="k">await</span> <span class="n">repo</span><span class="o">.</span><span class="n">get_by_id</span><span class="p">(</span><span class="n">user_id</span><span class="p">)</span>
|
||||
<a id="__codelineno-0-44" name="__codelineno-0-44" href="#__codelineno-0-44"></a> <span class="k">except</span> <span class="n">InvalidId</span><span class="p">:</span>
|
||||
<a id="__codelineno-0-45" name="__codelineno-0-45" href="#__codelineno-0-45"></a> <span class="k">raise</span> <span class="n">HTTPException</span><span class="p">(</span><span class="n">status_code</span><span class="o">=</span><span class="mi">400</span><span class="p">,</span> <span class="n">detail</span><span class="o">=</span><span class="s2">"Invalid user ID"</span><span class="p">)</span>
|
||||
<a id="__codelineno-0-46" name="__codelineno-0-46" href="#__codelineno-0-46"></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">user</span><span class="p">:</span>
|
||||
<a id="__codelineno-0-47" name="__codelineno-0-47" href="#__codelineno-0-47"></a> <span class="k">raise</span> <span class="n">HTTPException</span><span class="p">(</span><span class="n">status_code</span><span class="o">=</span><span class="mi">404</span><span class="p">,</span> <span class="n">detail</span><span class="o">=</span><span class="s2">"User not found"</span><span class="p">)</span>
|
||||
<a id="__codelineno-0-48" name="__codelineno-0-48" href="#__codelineno-0-48"></a> <span class="k">return</span> <span class="n">user</span>
|
||||
</code></pre></div>
|
||||
<blockquote>
|
||||
<p>Prefer exception <strong>handlers</strong> for the library-level exceptions (409/400 above) and per-endpoint <code>try/except</code> for domain decisions (404).</p>
|
||||
</blockquote>
|
||||
<hr />
|
||||
<h2 id="tips">💡 Tips</h2>
|
||||
<ul>
|
||||
<li>The <code>ValueError</code> populate guards are your friends: they surface data-shape drift (embedded docs, skipped population) at the exact call site.</li>
|
||||
<li>In dev, log the <code>CircularReferenceError.path</code> — it prints the visited <code>Class:id</code> chain.</li>
|
||||
<li>Never swallow <code>RuntimeError</code>s at startup; let the app fail to load so the misconfiguration is obvious.</li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h2 id="related">Related</h2>
|
||||
<ul>
|
||||
<li><a href="../03_use_cases/03_transactions/">03 – Transactions</a> · <a href="../03_use_cases/08_population/">08 – Population</a> · <a href="../03_use_cases/11_cache_lifecycle/">11 – Cache lifecycle</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user