Skip to content

Commit 3356735

Browse files
Merge latest changes from main
2 parents 1d4385b + bebe165 commit 3356735

File tree

9 files changed

+207
-48
lines changed

9 files changed

+207
-48
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,5 +164,6 @@ and submit a pull request.
164164

165165
### License
166166

167-
This project is licensed under the MIT License. See the LICENSE file for
168-
more details.
167+
This project is created and maintained by [Promptly Technologies,
168+
LLC](https://promptlytechnologies.com/) and licensed under the MIT
169+
License. See the LICENSE file for more details.

_quarto.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ website:
2020
text: Deployment
2121
- href: docs/contributing.qmd
2222
text: Contributing
23+
right:
24+
- icon: github
25+
href: https://github.com/promptly-technologies-llc/fastapi-jinja2-postgres-webapp
26+
page-footer:
27+
left: "Copyright 2024, Promptly Technologies, LLC. MIT License."
28+
right:
29+
- icon: github
30+
href: https://github.com/promptly-technologies-llc/fastapi-jinja2-postgres-webapp
2331
format:
2432
html:
2533
theme: cosmo

docs/architecture.qmd

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,110 @@ dot.render('static/data_flow', format='png', cleanup=True)
5959

6060
![Data flow diagram](static/data_flow.png)
6161

62-
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.
62+
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.
63+
64+
## Form validation flow
65+
66+
We've experimented with several approaches to validating form inputs in the FastAPI endpoints.
67+
68+
### Objectives
69+
70+
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.
71+
72+
This would keep the error handling consistent with the PRG pattern described in the [Architecture](https://promptlytechnologies.com/fastapi-jinja2-postgres-webapp/docs/architecture) section of this documentation.
73+
74+
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.
75+
76+
### Obstacles
77+
78+
One challenge is that if we redirect back to the page with the form, the page is re-rendered with empty form fields.
79+
80+
This can be overcome by passing the inputs from the request as context variables to the template.
81+
82+
But that's a bit clunky, because then we have to support form-specific context variables in every form page and corresponding GET endpoint.
83+
84+
Also, we have to:
85+
86+
1. access the request object (which is not by default available to our middleware), and
87+
2. extract the form inputs (at least one of which is invalid in this error case), and
88+
3. 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).
89+
90+
Solving these challenges is possible, but gets high-complexity pretty quickly.
91+
92+
### Approaches
93+
94+
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.
95+
96+
Here are some patterns we've considered for server-side error handling:
97+
98+
<style>
99+
.styled-table, .styled-table th, .styled-table td {
100+
border: 1px solid black;
101+
padding: 8px;
102+
border-collapse: collapse;
103+
}
104+
105+
.styled-table th:nth-child(1) { width: 5%; }
106+
.styled-table th:nth-child(2) { width: 50%; }
107+
.styled-table th:nth-child(3),
108+
.styled-table th:nth-child(4),
109+
.styled-table th:nth-child(5) { width: 15%; }
110+
.styled-table th:nth-child(6) { width: 10%; }
111+
</style>
112+
113+
<table class="styled-table">
114+
<thead>
115+
<tr>
116+
<th>ID</th>
117+
<th>Approach</th>
118+
<th>Returns to same page</th>
119+
<th>Preserves form inputs</th>
120+
<th>Follows PRG pattern</th>
121+
<th>Complexity</th>
122+
</tr>
123+
</thead>
124+
<tbody>
125+
<tr>
126+
<td>1</td>
127+
<td>Validate with Pydantic dependency, catch and redirect from middleware (with exception message as context) to an error page with "go back" button</td>
128+
<td>No</td>
129+
<td>Yes</td>
130+
<td>Yes</td>
131+
<td>Low</td>
132+
</tr>
133+
<tr>
134+
<td>2</td>
135+
<td>Validate in FastAPI endpoint function body, redirect to origin page with error message query param</td>
136+
<td>Yes</td>
137+
<td>No</td>
138+
<td>Yes</td>
139+
<td>Medium</td>
140+
</tr>
141+
<tr>
142+
<td>3</td>
143+
<td>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</td>
144+
<td>Yes</td>
145+
<td>Yes</td>
146+
<td>Yes</td>
147+
<td>High</td>
148+
</tr>
149+
<tr>
150+
<td>4</td>
151+
<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>
152+
<td>Yes</td>
153+
<td>Yes</td>
154+
<td>Yes</td>
155+
<td>High</td>
156+
</tr>
157+
<tr>
158+
<td>5</td>
159+
<td>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</td>
160+
<td>Yes</td>
161+
<td>Yes</td>
162+
<td>No</td>
163+
<td>Low</td>
164+
</tr>
165+
</tbody>
166+
</table>
167+
168+
Presently this template primarily uses option 1 but also supports option 2. Ultimately, I think option 5 will be preferable; support for that [is planned](https://github.com/Promptly-Technologies-LLC/fastapi-jinja2-postgres-webapp/issues/5) for a future update or fork of this template.

docs/authentication.qmd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ This template implements a comprehensive authentication system with security bes
3232

3333
The diagrams below show the main authentication flows.
3434

35-
### Registration and login flow
35+
## Registration and login flow
3636

3737
``` {python}
3838
#| echo: false
@@ -87,7 +87,7 @@ auth.render('static/auth_flow', format='png', cleanup=True)
8787

8888
![Registration and login flow](static/auth_flow.png)
8989

90-
### Password reset flow
90+
## Password reset flow
9191

9292
``` {python}
9393
#| echo: false

docs/contributing.qmd

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,46 @@ title: "Contributing"
44

55
## Contributors
66

7-
Fork the repository, create a new branch, make your changes, and submit a pull request.
7+
### Opening issues and bug reports
88

9-
### Render the documentation
9+
When opening a new issue or submitting a bug report, please include:
1010

11-
The README and documentation website are rendered with [Quarto](https://quarto.org/docs/). Make changes to the `.qmd` files in the root folder and the `docs` folder. Then run the following commands to render:
11+
1. A clear, descriptive title
12+
2. For bug reports:
13+
- Description of the expected behavior
14+
- Description of the actual behavior
15+
- Steps to reproduce the issue
16+
- Version information (OS, Python version, package version)
17+
- Any relevant error messages or screenshots
18+
3. For feature requests:
19+
- Description of the proposed feature
20+
- Use case or motivation for the feature
21+
- Any implementation suggestions (optional)
22+
23+
Labels help categorize issues:
24+
- Use `bug` for reporting problems
25+
- Use `enhancement` for feature requests
26+
- Use `documentation` for documentation improvements
27+
- Use `question` for general queries
28+
29+
### Contributing code
30+
31+
To contribute code to the project:
32+
33+
1. Fork the repository and clone your fork locally
34+
2. Create a new branch from `main` with a descriptive name
35+
3. Review the [customization](https://promptlytechnologies.com/fastapi-jinja2-postgres-webapp/customization.html), [architecture](https://promptlytechnologies.com/fastapi-jinja2-postgres-webapp/architecture.html), and [authentication](https://promptlytechnologies.com/fastapi-jinja2-postgres-webapp/authentication.html) pages for guidance on design patterns and code structure and style
36+
4. Ensure all tests pass, including `mypy` type checking
37+
5. Stage, commit, and push your changes to the branch:
38+
- Use clear, descriptive commit messages
39+
- Keep commits focused and atomic
40+
6. Submit your pull request:
41+
- Provide a clear description of the changes
42+
- Link to any related issues
43+
44+
### Rendering the documentation
45+
46+
The README and documentation website are rendered with [Quarto](https://quarto.org/docs/). If you ,make changes to the `.qmd` files in the root folder and the `docs` folder, run the following commands to re-render the docs:
1247

1348
``` bash
1449
# To render the documentation website
@@ -19,17 +54,22 @@ quarto render index.qmd --output-dir . --output README.md --to gfm
1954

2055
Due to a quirk of Quarto, an unnecessary `index.html` file is created in the root folder when the README is rendered. This file can be safely deleted.
2156

57+
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.
58+
2259
## Maintainers
2360

24-
### Increment the version
61+
### Git flow
2562

26-
Run the following command to increment the version:
63+
When creating new features,
2764

28-
``` bash
29-
poetry version patch minor
30-
```
65+
1. Open a Github issue with the label `feature` and assign it to yourself.
66+
2. Create a new branch from the issue sidebar.
67+
3. Follow the instructions in the popup to check out the branch locally and make your changes on the branch.
68+
4. Commit your changes and push to the branch.
69+
5. When you are ready to merge, open a pull request from the branch to main.
70+
6. Assign someone else for code review.
3171

32-
### Publish the documentation
72+
### Publishing the documentation
3373

3474
To publish the documentation to GitHub Pages, run the following command:
3575

docs/customization.qmd

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,3 @@
22
title: "Customization"
33
---
44

5-
## Under construction

docs/installation.qmd

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: "Installation"
33
---
44

5-
## Install development dependencies in a VSCode Dev Container
5+
## Install all dependencies in a VSCode Dev Container
66

77
If you use VSCode with Docker to develop in a container, the following VSCode Dev Container configuration will install all dependencies:
88

@@ -45,48 +45,53 @@ For Windows:
4545

4646
- No installation required
4747

48-
### Quarto CLI and Graphviz
48+
### Python dependencies
4949

50-
- [Quarto CLI](https://quarto.org/docs/get-started/)
50+
1. Install Poetry
5151

52+
``` bash
53+
pipx install poetry
54+
```
5255

53-
For macOS:
56+
2. Install project dependencies
5457

5558
``` bash
56-
brew install graphviz
59+
poetry install
5760
```
5861

59-
For Ubuntu/Debian:
62+
3. Activate shell
6063

6164
``` bash
62-
sudo apt update && sudo apt install -y graphviz
65+
poetry shell
6366
```
6467

65-
For Windows:
68+
(Note: You will need to activate the shell every time you open a new terminal session. Alternatively, you can use the `poetry run` prefix before other commands to run them without activating the shell.)
6669

67-
- Download and install from [Graphviz.org](https://graphviz.org/download/#windows)
70+
## Install documentation dependencies manually
6871

69-
### Python dependencies
72+
### Quarto CLI
7073

71-
1. Install Poetry
74+
To render the project documentation, you will need to download and install the [Quarto CLI](https://quarto.org/docs/get-started/) for your operating system.
7275

73-
``` bash
74-
pipx install poetry
75-
```
76+
### Graphviz
7677

77-
2. Install project dependencies
78+
Architecture diagrams in the documentation are rendered with [Graphviz](https://graphviz.org/).
79+
80+
For macOS:
7881

7982
``` bash
80-
poetry install
83+
brew install graphviz
8184
```
8285

83-
3. Activate shell
86+
For Ubuntu/Debian:
8487

8588
``` bash
86-
poetry shell
89+
sudo apt update && sudo apt install -y graphviz
8790
```
8891

89-
(Note: You will need to activate the shell every time you open a new terminal session. Alternatively, you can use the `poetry run` prefix before other commands to run them without activating the shell.)
92+
For Windows:
93+
94+
- Download and install from [Graphviz.org](https://graphviz.org/download/#windows)
9095

9196
## Set environment variables
9297

index.qmd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,4 @@ Your contributions are welcome! See the [issues page](https://github.com/promptl
133133

134134
### License
135135

136-
This project is licensed under the MIT License. See the LICENSE file for more details.
136+
This project is created and maintained by [Promptly Technologies, LLC](https://promptlytechnologies.com/) and licensed under the MIT License. See the LICENSE file for more details.

poetry.lock

Lines changed: 13 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)