Skip to content

Commit 4fcfa8b

Browse files
Built site for gh-pages
1 parent 26549fb commit 4fcfa8b

File tree

4 files changed

+132
-54
lines changed

4 files changed

+132
-54
lines changed

.nojekyll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
f3f0e57a
1+
8be918e2

docs/architecture.html

Lines changed: 129 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -208,65 +208,143 @@ <h3 class="anchored" data-anchor-id="obstacles">Obstacles</h3>
208208
<h3 class="anchored" data-anchor-id="approaches">Approaches</h3>
209209
<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>
210210
<p>Here are some patterns we’ve considered for server-side error handling:</p>
211-
<table class="caption-top table">
212-
<colgroup>
213-
<col style="width: 6%">
214-
<col style="width: 12%">
215-
<col style="width: 22%">
216-
<col style="width: 22%">
217-
<col style="width: 21%">
218-
<col style="width: 14%">
219-
</colgroup>
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: 5%; }
219+
.styled-table th:nth-child(2) { width: 50%; }
220+
.styled-table th:nth-child(3),
221+
.styled-table th:nth-child(4),
222+
.styled-table th:nth-child(5) { width: 15%; }
223+
.styled-table th:nth-child(6) { width: 10%; }
224+
</style>
225+
<table class="styled-table">
220226
<thead>
221-
<tr class="header">
222-
<th>ID</th>
223-
<th>Approach</th>
224-
<th>Returns to same page</th>
225-
<th>Preserves form inputs</th>
226-
<th>Follows PRG pattern</th>
227-
<th>Complexity</th>
227+
<tr>
228+
<th>
229+
ID
230+
</th>
231+
<th>
232+
Approach
233+
</th>
234+
<th>
235+
Returns to same page
236+
</th>
237+
<th>
238+
Preserves form inputs
239+
</th>
240+
<th>
241+
Follows PRG pattern
242+
</th>
243+
<th>
244+
Complexity
245+
</th>
228246
</tr>
229247
</thead>
230248
<tbody>
231-
<tr class="odd">
232-
<td>1</td>
233-
<td>Validate with Pydantic dependency, catch and redirect from middleware (with exception message as context) to an error page with “go back” button</td>
234-
<td>No</td>
235-
<td>Yes</td>
236-
<td>Yes</td>
237-
<td>Low</td>
249+
<tr>
250+
<td>
251+
1
252+
</td>
253+
<td>
254+
Validate with Pydantic dependency, catch and redirect from middleware (with exception message as context) to an error page with “go back” button
255+
</td>
256+
<td>
257+
No
258+
</td>
259+
<td>
260+
Yes
261+
</td>
262+
<td>
263+
Yes
264+
</td>
265+
<td>
266+
Low
267+
</td>
238268
</tr>
239-
<tr class="even">
240-
<td>2</td>
241-
<td>Validate in FastAPI endpoint function body, redirect to origin page with error message query param</td>
242-
<td>Yes</td>
243-
<td>No</td>
244-
<td>Yes</td>
245-
<td>Medium</td>
269+
<tr>
270+
<td>
271+
2
272+
</td>
273+
<td>
274+
Validate in FastAPI endpoint function body, redirect to origin page with error message query param
275+
</td>
276+
<td>
277+
Yes
278+
</td>
279+
<td>
280+
No
281+
</td>
282+
<td>
283+
Yes
284+
</td>
285+
<td>
286+
Medium
287+
</td>
246288
</tr>
247-
<tr class="odd">
248-
<td>3</td>
249-
<td>Validate in FastAPI endpoint function body, redirect to origin page with error message query param and form inputs as context</td>
250-
<td>Yes</td>
251-
<td>Yes</td>
252-
<td>Yes</td>
253-
<td>High</td>
289+
<tr>
290+
<td>
291+
3
292+
</td>
293+
<td>
294+
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
295+
</td>
296+
<td>
297+
Yes
298+
</td>
299+
<td>
300+
Yes
301+
</td>
302+
<td>
303+
Yes
304+
</td>
305+
<td>
306+
High
307+
</td>
254308
</tr>
255-
<tr class="even">
256-
<td>4</td>
257-
<td>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</td>
258-
<td>Yes</td>
259-
<td>Yes</td>
260-
<td>Yes</td>
261-
<td>High</td>
309+
<tr>
310+
<td>
311+
4
312+
</td>
313+
<td>
314+
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
315+
</td>
316+
<td>
317+
Yes
318+
</td>
319+
<td>
320+
Yes
321+
</td>
322+
<td>
323+
Yes
324+
</td>
325+
<td>
326+
High
327+
</td>
262328
</tr>
263-
<tr class="odd">
264-
<td>5</td>
265-
<td>Validate in either Pydantic dependency or function endpoint body and directly return error message in JSON, then mount it with HTMX or some simple layout-level Javascript</td>
266-
<td>Yes</td>
267-
<td>Yes</td>
268-
<td>No</td>
269-
<td>Low</td>
329+
<tr>
330+
<td>
331+
5
332+
</td>
333+
<td>
334+
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
335+
</td>
336+
<td>
337+
Yes
338+
</td>
339+
<td>
340+
Yes
341+
</td>
342+
<td>
343+
No
344+
</td>
345+
<td>
346+
Low
347+
</td>
270348
</tr>
271349
</tbody>
272350
</table>

search.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181
"href": "docs/architecture.html#form-validation-flow",
8282
"title": "Architecture",
8383
"section": "Form validation flow",
84-
"text": "Form validation flow\nWe’ve experimented with several approaches to validating form inputs in the FastAPI endpoints.\n\nObjectives\nIdeally, 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.\nThis would keep the error handling consistent with the PRG pattern described in the Architecture section of this documentation.\nTo 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.\n\n\nObstacles\nOne challenge is that if we redirect back to the page with the form, the page is re-rendered with empty form fields.\nThis can be overcome by passing the inputs from the request as context variables to the template.\nBut that’s a bit clunky, because then we have to support form-specific context variables in every form page and corresponding GET endpoint.\nAlso, we have to:\n\naccess the request object (which is not by default available to our middleware), and\nextract the form inputs (at least one of which is invalid in this error case), and\npass 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).\n\nSolving these challenges is possible, but gets high-complexity pretty quickly.\n\n\nApproaches\nThe 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.\nHere are some patterns we’ve considered for server-side error handling:\n\n\n\n\n\n\n\n\n\n\n\nID\nApproach\nReturns to same page\nPreserves form inputs\nFollows PRG pattern\nComplexity\n\n\n\n\n1\nValidate with Pydantic dependency, catch and redirect from middleware (with exception message as context) to an error page with “go back” button\nNo\nYes\nYes\nLow\n\n\n2\nValidate in FastAPI endpoint function body, redirect to origin page with error message query param\nYes\nNo\nYes\nMedium\n\n\n3\nValidate in FastAPI endpoint function body, redirect to origin page with error message query param and form inputs as context\nYes\nYes\nYes\nHigh\n\n\n4\nValidate 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\nYes\nYes\nYes\nHigh\n\n\n5\nValidate in either Pydantic dependency or function endpoint body and directly return error message in JSON, then mount it with HTMX or some simple layout-level Javascript\nYes\nYes\nNo\nLow\n\n\n\nPresently this template primarily uses option 1 but also supports option 2. Ultimately, I think option 5 will be preferable; support for that is planned for a future update or fork of this template."
84+
"text": "Form validation flow\nWe’ve experimented with several approaches to validating form inputs in the FastAPI endpoints.\n\nObjectives\nIdeally, 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.\nThis would keep the error handling consistent with the PRG pattern described in the Architecture section of this documentation.\nTo 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.\n\n\nObstacles\nOne challenge is that if we redirect back to the page with the form, the page is re-rendered with empty form fields.\nThis can be overcome by passing the inputs from the request as context variables to the template.\nBut that’s a bit clunky, because then we have to support form-specific context variables in every form page and corresponding GET endpoint.\nAlso, we have to:\n\naccess the request object (which is not by default available to our middleware), and\nextract the form inputs (at least one of which is invalid in this error case), and\npass 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).\n\nSolving these challenges is possible, but gets high-complexity pretty quickly.\n\n\nApproaches\nThe 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.\nHere are some patterns we’ve considered for server-side error handling:\n\n\n\n\n\nID\n\n\nApproach\n\n\nReturns to same page\n\n\nPreserves form inputs\n\n\nFollows PRG pattern\n\n\nComplexity\n\n\n\n\n\n\n1\n\n\nValidate with Pydantic dependency, catch and redirect from middleware (with exception message as context) to an error page with “go back” button\n\n\nNo\n\n\nYes\n\n\nYes\n\n\nLow\n\n\n\n\n2\n\n\nValidate in FastAPI endpoint function body, redirect to origin page with error message query param\n\n\nYes\n\n\nNo\n\n\nYes\n\n\nMedium\n\n\n\n\n3\n\n\nValidate 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\n\n\nYes\n\n\nYes\n\n\nYes\n\n\nHigh\n\n\n\n\n4\n\n\nValidate 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\n\n\nYes\n\n\nYes\n\n\nYes\n\n\nHigh\n\n\n\n\n5\n\n\nValidate 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\n\n\nYes\n\n\nYes\n\n\nNo\n\n\nLow\n\n\n\n\nPresently this template primarily uses option 1 but also supports option 2. Ultimately, I think option 5 will be preferable; support for that is planned for a future update or fork of this template."
8585
},
8686
{
8787
"objectID": "docs/authentication.html",

sitemap.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
</url>
1515
<url>
1616
<loc>https://Promptly-Technologies-LLC.github.io/fastapi-jinja2-postgres-webapp/docs/architecture.html</loc>
17-
<lastmod>2024-11-23T16:49:49.060Z</lastmod>
17+
<lastmod>2024-11-23T17:14:34.404Z</lastmod>
1818
</url>
1919
<url>
2020
<loc>https://Promptly-Technologies-LLC.github.io/fastapi-jinja2-postgres-webapp/docs/authentication.html</loc>

0 commit comments

Comments
 (0)