Skip to content

Commit e2f0db3

Browse files
Built site for gh-pages
1 parent ea5eaf5 commit e2f0db3

File tree

5 files changed

+20
-13
lines changed

5 files changed

+20
-13
lines changed

.nojekyll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
5ea02550
1+
d2f987ad

docs/customization.html

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,12 @@ <h4 class="anchored" data-anchor-id="context-variables">Context variables</h4>
314314
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a> )</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
315315
<p>In this example, the <code>welcome.html</code> template will receive two pieces of context: the user’s <code>request</code>, which is always passed automatically by FastAPI, and a <code>username</code> variable, which we specify as “Alice”. We can then use the <code>{ username }</code> syntax in the <code>welcome.html</code> template (or any of its parent or child templates) to insert the value into the HTML.</p>
316316
</section>
317+
<section id="form-validation-strategy" class="level4">
318+
<h4 class="anchored" data-anchor-id="form-validation-strategy">Form validation strategy</h4>
319+
<p>While this template includes comprehensive server-side validation through Pydantic models and custom validators, it’s important to note that server-side validation should be treated as a fallback security measure. If users ever see the <code>validation_error.html</code> template, it indicates that our client-side validation has failed to catch invalid input before it reaches the server.</p>
320+
<p>Best practices dictate implementing thorough client-side validation via JavaScript and/or HTML <code>input</code> element <code>pattern</code> attributes to: - Provide immediate feedback to users - Reduce server load - Improve user experience by avoiding round-trips to the server - Prevent malformed data from ever reaching the backend</p>
321+
<p>Server-side validation remains essential as a security measure against malicious requests that bypass client-side validation, but it should rarely be encountered during normal user interaction. See <code>templates/authentication/register.html</code> for a client-side form validation example involving both JavaScript and HTML regex <code>pattern</code> matching.</p>
322+
</section>
317323
</section>
318324
<section id="writing-type-annotated-code" class="level3">
319325
<h3 class="anchored" data-anchor-id="writing-type-annotated-code">Writing type annotated code</h3>
@@ -407,12 +413,13 @@ <h4 class="anchored" data-anchor-id="models-and-relationships">Models and relati
407413
<li><code>RolePermissionLink</code>: Maps roles to their allowed permissions</li>
408414
<li><code>PasswordResetToken</code>: Manages password reset functionality</li>
409415
</ul>
410-
<p>Models can have relationships with other models using SQLModel’s <code>Relationship</code> field. For example:</p>
411-
<div class="sourceCode" id="cb8"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> User(SQLModel, table<span class="op">=</span><span class="va">True</span>):</span>
412-
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a> <span class="co"># ... other fields ...</span></span>
413-
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a> organization: Optional[<span class="st">"Organization"</span>] <span class="op">=</span> Relationship(back_populates<span class="op">=</span><span class="st">"users"</span>)</span>
414-
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a> role: Optional[<span class="st">"Role"</span>] <span class="op">=</span> Relationship(back_populates<span class="op">=</span><span class="st">"users"</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
415-
<p>This creates a many-to-one relationship between users and organizations, and between users and roles.</p>
416+
<p>Here’s an entity-relationship diagram (ERD) of the current database schema, automatically generated from our SQLModel definitions:</p>
417+
<div class="quarto-figure quarto-figure-center">
418+
<figure class="figure">
419+
<p><img src="static/schema.png" class="img-fluid figure-img"></p>
420+
<figcaption>Database Schema</figcaption>
421+
</figure>
422+
</div>
416423
</section>
417424
<section id="database-operations" class="level4">
418425
<h4 class="anchored" data-anchor-id="database-operations">Database operations</h4>
@@ -423,10 +430,10 @@ <h4 class="anchored" data-anchor-id="database-operations">Database operations</h
423430
<li><code>get_session()</code>: Provides a database session for performing operations</li>
424431
</ul>
425432
<p>To perform database operations in route handlers, inject the database session as a dependency:</p>
426-
<div class="sourceCode" id="cb9"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="at">@app.get</span>(<span class="st">"/users"</span>)</span>
427-
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="cf">async</span> <span class="kw">def</span> get_users(session: Session <span class="op">=</span> Depends(get_session)):</span>
428-
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a> users <span class="op">=</span> session.<span class="bu">exec</span>(select(User)).<span class="bu">all</span>()</span>
429-
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> users</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
433+
<div class="sourceCode" id="cb8"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="at">@app.get</span>(<span class="st">"/users"</span>)</span>
434+
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="cf">async</span> <span class="kw">def</span> get_users(session: Session <span class="op">=</span> Depends(get_session)):</span>
435+
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a> users <span class="op">=</span> session.<span class="bu">exec</span>(select(User)).<span class="bu">all</span>()</span>
436+
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> users</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
430437
<p>The session automatically handles transaction management, ensuring that database operations are atomic and consistent.</p>
431438

432439

docs/static/schema.png

52.4 KB
Loading

0 commit comments

Comments
 (0)