Skip to content

Commit 1320f47

Browse files
Built site for gh-pages
1 parent 7483be5 commit 1320f47

15 files changed

+1519
-597
lines changed

.nojekyll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
ebdc9620
1+
bab9c6a9

docs/architecture.html

Lines changed: 4 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
33

44
<meta charset="utf-8">
5-
<meta name="generator" content="quarto-1.6.42">
5+
<meta name="generator" content="quarto-1.6.43">
66

77
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
88

@@ -35,7 +35,7 @@
3535
<script src="../site_libs/quarto-html/tippy.umd.min.js"></script>
3636
<script src="../site_libs/quarto-html/anchor.min.js"></script>
3737
<link href="../site_libs/quarto-html/tippy.css" rel="stylesheet">
38-
<link href="../site_libs/quarto-html/quarto-syntax-highlighting-2f5df379a58b258e96c21c0638c20c03.css" rel="stylesheet" id="quarto-text-highlighting-styles">
38+
<link href="../site_libs/quarto-html/quarto-syntax-highlighting-d4d76bf8491c20bad77d141916dc28e1.css" rel="stylesheet" id="quarto-text-highlighting-styles">
3939
<script src="../site_libs/bootstrap/bootstrap.min.js"></script>
4040
<link href="../site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
4141
<link href="../site_libs/bootstrap/bootstrap-8647a4a42273f773479d27c00df3f9ed.min.css" rel="stylesheet" append-hash="true" id="quarto-bootstrap" data-mode="light">
@@ -140,12 +140,6 @@ <h2 id="toc-title">On this page</h2>
140140

141141
<ul>
142142
<li><a href="#data-flow" id="toc-data-flow" class="nav-link active" data-scroll-target="#data-flow">Data flow</a></li>
143-
<li><a href="#form-validation-flow" id="toc-form-validation-flow" class="nav-link" data-scroll-target="#form-validation-flow">Form validation flow</a>
144-
<ul class="collapse">
145-
<li><a href="#objectives" id="toc-objectives" class="nav-link" data-scroll-target="#objectives">Objectives</a></li>
146-
<li><a href="#obstacles" id="toc-obstacles" class="nav-link" data-scroll-target="#obstacles">Obstacles</a></li>
147-
<li><a href="#approaches" id="toc-approaches" class="nav-link" data-scroll-target="#approaches">Approaches</a></li>
148-
</ul></li>
149143
</ul>
150144
</nav>
151145
</div>
@@ -180,159 +174,10 @@ <h2 class="anchored" data-anchor-id="data-flow">Data flow</h2>
180174
<figcaption>Data flow diagram</figcaption>
181175
</figure>
182176
</div>
183-
<p>The advantage of the PRG pattern is that it is very straightforward to implement and keeps most of the rendering logic on the server side. The disadvantage is that it requires an extra round trip to the database to fetch the updated data, and re-rendering the entire page template may be less efficient than a partial page update on the client side.</p>
184-
</section>
185-
<section id="form-validation-flow" class="level2">
186-
<h2 class="anchored" data-anchor-id="form-validation-flow">Form validation flow</h2>
187-
<p>We’ve experimented with several approaches to validating form inputs in the FastAPI endpoints.</p>
188-
<section id="objectives" class="level3">
189-
<h3 class="anchored" data-anchor-id="objectives">Objectives</h3>
190-
<p>Ideally, on an invalid input, we would redirect the user back to the form, preserving their inputs and displaying an error message about which input was invalid.</p>
191-
<p>This would keep the error handling consistent with the PRG pattern described in the <a href="https://promptlytechnologies.com/fastapi-jinja2-postgres-webapp/docs/architecture">Architecture</a> section of this documentation.</p>
192-
<p>To keep the code DRY, we’d also like to handle such validation with Pydantic dependencies, Python exceptions, and exception-handling middleware as much as possible.</p>
193-
</section>
194-
<section id="obstacles" class="level3">
195-
<h3 class="anchored" data-anchor-id="obstacles">Obstacles</h3>
196-
<p>One challenge is that if we redirect back to the page with the form, the page is re-rendered with empty form fields.</p>
197-
<p>This can be overcome by passing the inputs from the request as context variables to the template.</p>
198-
<p>But that’s a bit clunky, because then we have to support form-specific context variables in every form page and corresponding GET endpoint.</p>
199-
<p>Also, we have to:</p>
200-
<ol type="1">
201-
<li>access the request object (which is not by default available to our middleware), and</li>
202-
<li>extract the form inputs (at least one of which is invalid in this error case), and</li>
203-
<li>pass the form inputs to the template (which is a bit challenging to do in a DRY way since there are different sets of form inputs for different forms).</li>
204-
</ol>
205-
<p>Solving these challenges is possible, but gets high-complexity pretty quickly.</p>
206-
</section>
207-
<section id="approaches" class="level3">
208-
<h3 class="anchored" data-anchor-id="approaches">Approaches</h3>
209-
<p>The best solution, I think, is to use really robust client-side form validation to prevent invalid inputs from being sent to the server in the first place. That makes it less important what we do on the server side, although we still need to handle the server-side error case as a backup in the event that something slips past our validation on the client side.</p>
210-
<p>Here are some patterns we’ve considered for server-side error handling:</p>
211-
<style>
212-
.styled-table, .styled-table th, .styled-table td {
213-
border: 1px solid black;
214-
padding: 8px;
215-
border-collapse: collapse;
216-
}
217-
218-
.styled-table th:nth-child(1) { width: 50%; }
219-
.styled-table th:nth-child(2),
220-
.styled-table th:nth-child(3),
221-
.styled-table th:nth-child(4) { width: 15%; }
222-
.styled-table th:nth-child(5) { width: 10%; }
223-
</style>
224-
<table class="styled-table">
225-
<thead>
226-
<tr>
227-
<th>
228-
Approach
229-
</th>
230-
<th>
231-
Returns to same page
232-
</th>
233-
<th>
234-
Preserves form inputs
235-
</th>
236-
<th>
237-
Follows PRG pattern
238-
</th>
239-
<th>
240-
Complexity
241-
</th>
242-
</tr>
243-
</thead>
244-
<tbody>
245-
<tr>
246-
<td>
247-
Validate with Pydantic dependency, catch and redirect from middleware (with exception message as context) to an error page with “go back” button
248-
</td>
249-
<td>
250-
No
251-
</td>
252-
<td>
253-
Yes
254-
</td>
255-
<td>
256-
Yes
257-
</td>
258-
<td>
259-
Low
260-
</td>
261-
</tr>
262-
<tr>
263-
<td>
264-
Validate in FastAPI endpoint function body, redirect to origin page with error message query param
265-
</td>
266-
<td>
267-
Yes
268-
</td>
269-
<td>
270-
No
271-
</td>
272-
<td>
273-
Yes
274-
</td>
275-
<td>
276-
Medium
277-
</td>
278-
</tr>
279-
<tr>
280-
<td>
281-
Validate in FastAPI endpoint function body, redirect to origin page with error message query param and form inputs as context so we can re-render page with original form inputs
282-
</td>
283-
<td>
284-
Yes
285-
</td>
286-
<td>
287-
Yes
288-
</td>
289-
<td>
290-
Yes
291-
</td>
292-
<td>
293-
High
294-
</td>
295-
</tr>
296-
<tr>
297-
<td>
298-
Validate with Pydantic dependency, use session context to get form inputs from request, redirect to origin page from middleware with exception message and form inputs as context so we can re-render page with original form inputs
299-
</td>
300-
<td>
301-
Yes
302-
</td>
303-
<td>
304-
Yes
305-
</td>
306-
<td>
307-
Yes
308-
</td>
309-
<td>
310-
High
311-
</td>
312-
</tr>
313-
<tr>
314-
<td>
315-
Validate in either Pydantic dependency or function endpoint body and directly return error message or error toast HTML partial in JSON, then mount error toast with HTMX or some simple layout-level Javascript
316-
</td>
317-
<td>
318-
Yes
319-
</td>
320-
<td>
321-
Yes
322-
</td>
323-
<td>
324-
No
325-
</td>
326-
<td>
327-
Low
328-
</td>
329-
</tr>
330-
</tbody>
331-
</table>
332-
<p>Presently this template primarily uses option 1 but also supports option 2. Ultimately, I think option 5 will be preferable; support for that <a href="https://github.com/Promptly-Technologies-LLC/fastapi-jinja2-postgres-webapp/issues/5">is planned</a> for a future update or fork of this template.</p>
177+
<p>The advantage of the PRG pattern is that it is very straightforward to implement and keeps most of the rendering logic on the server side. One disadvantage is that it requires an extra round trip to the database to fetch the updated data, and re-rendering the entire page template may be less efficient than a partial page update on the client side. Another disadvantage is that it if the user makes an invalid form submission, they will see an error page and will have to click the browser’s “back” button to get back to the form with their original form inputs.</p>
178+
<p>A future iteration of this application will use HTMX to update the page in place, so that on an invalid submission an error toast is displayed without a page reload (thus preserving the user’s scroll position and form inputs).</p>
333179

334180

335-
</section>
336181
</section>
337182

338183
</main> <!-- /main -->

docs/authentication.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
33

44
<meta charset="utf-8">
5-
<meta name="generator" content="quarto-1.6.42">
5+
<meta name="generator" content="quarto-1.6.43">
66

77
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
88

@@ -35,7 +35,7 @@
3535
<script src="../site_libs/quarto-html/tippy.umd.min.js"></script>
3636
<script src="../site_libs/quarto-html/anchor.min.js"></script>
3737
<link href="../site_libs/quarto-html/tippy.css" rel="stylesheet">
38-
<link href="../site_libs/quarto-html/quarto-syntax-highlighting-2f5df379a58b258e96c21c0638c20c03.css" rel="stylesheet" id="quarto-text-highlighting-styles">
38+
<link href="../site_libs/quarto-html/quarto-syntax-highlighting-d4d76bf8491c20bad77d141916dc28e1.css" rel="stylesheet" id="quarto-text-highlighting-styles">
3939
<script src="../site_libs/bootstrap/bootstrap.min.js"></script>
4040
<link href="../site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
4141
<link href="../site_libs/bootstrap/bootstrap-8647a4a42273f773479d27c00df3f9ed.min.css" rel="stylesheet" append-hash="true" id="quarto-bootstrap" data-mode="light">

docs/contributing.html

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
33

44
<meta charset="utf-8">
5-
<meta name="generator" content="quarto-1.6.42">
5+
<meta name="generator" content="quarto-1.6.43">
66

77
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
88

@@ -69,7 +69,7 @@
6969
<script src="../site_libs/quarto-html/tippy.umd.min.js"></script>
7070
<script src="../site_libs/quarto-html/anchor.min.js"></script>
7171
<link href="../site_libs/quarto-html/tippy.css" rel="stylesheet">
72-
<link href="../site_libs/quarto-html/quarto-syntax-highlighting-2f5df379a58b258e96c21c0638c20c03.css" rel="stylesheet" id="quarto-text-highlighting-styles">
72+
<link href="../site_libs/quarto-html/quarto-syntax-highlighting-d4d76bf8491c20bad77d141916dc28e1.css" rel="stylesheet" id="quarto-text-highlighting-styles">
7373
<script src="../site_libs/bootstrap/bootstrap.min.js"></script>
7474
<link href="../site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
7575
<link href="../site_libs/bootstrap/bootstrap-8647a4a42273f773479d27c00df3f9ed.min.css" rel="stylesheet" append-hash="true" id="quarto-bootstrap" data-mode="light">
@@ -255,11 +255,14 @@ <h3 class="anchored" data-anchor-id="contributing-code">Contributing code</h3>
255255
</section>
256256
<section id="rendering-the-documentation" class="level3">
257257
<h3 class="anchored" data-anchor-id="rendering-the-documentation">Rendering the documentation</h3>
258-
<p>The README and documentation website are rendered with <a href="https://quarto.org/docs/">Quarto</a>. If you ,make changes to the <code>.qmd</code> files in the root folder and the <code>docs</code> folder, run the following commands to re-render the docs:</p>
259-
<div class="sourceCode" id="cb1"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co"># To render the documentation website</span></span>
260-
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="ex">quarto</span> render</span>
261-
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="co"># To render the README</span></span>
262-
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="ex">quarto</span> render index.qmd <span class="at">--output-dir</span> . <span class="at">--output</span> README.md <span class="at">--to</span> gfm</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
258+
<p>The README and documentation website are rendered with <a href="https://quarto.org/docs/">Quarto</a>. If you make changes to the <code>.qmd</code> files in the root folder and the <code>docs</code> folder, you will need to re-render the docs with Quarto.</p>
259+
<p>Quarto expects environment variables to be set in a file called <code>_environment</code>, so before running Quarto render commands, you should copy your <code>.env</code> file to <code>_environment</code>.</p>
260+
<div class="sourceCode" id="cb1"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co"># To copy the .env file to _environment</span></span>
261+
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="fu">cp</span> .env _environment</span>
262+
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="co"># To render the documentation website</span></span>
263+
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="ex">uv</span> run quarto render</span>
264+
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="co"># To render the README</span></span>
265+
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="ex">uv</span> run quarto render index.qmd <span class="at">--output-dir</span> . <span class="at">--output</span> README.md <span class="at">--to</span> gfm</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
263266
<p>Due to a quirk of Quarto, an unnecessary <code>index.html</code> file is created in the root folder when the README is rendered. This file can be safely deleted.</p>
264267
<p>Note that even if your pull request is merged, your changes will not be reflected on the live website until a maintainer republishes the docs.</p>
265268
</section>
@@ -281,7 +284,7 @@ <h3 class="anchored" data-anchor-id="git-flow">Git flow</h3>
281284
<section id="publishing-the-documentation" class="level3">
282285
<h3 class="anchored" data-anchor-id="publishing-the-documentation">Publishing the documentation</h3>
283286
<p>To publish the documentation to GitHub Pages, run the following command:</p>
284-
<div class="sourceCode" id="cb2"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ex">quarto</span> publish gh-pages</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
287+
<div class="sourceCode" id="cb2"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ex">uv</span> run quarto publish gh-pages</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
285288

286289

287290
</section>

0 commit comments

Comments
 (0)