Python FastAPI Tutorial (Part 9): Frontend Forms - Connecting JavaScript to Your API
Based on Corey Schafer's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.
A create-post modal is added to layout.html so users can create posts from any page without navigating away.
Briefing
A working CRUD workflow now runs from the browser: Bootstrap modals collect user input, JavaScript uses the fetch API to call FastAPI JSON endpoints, and the UI shows success or validation errors without redirecting. The core move is wiring a “Create post” form into the shared layout template so it’s available from any page, then standardizing the request/response pattern—serialize form fields to JSON, send them to the API, parse the JSON response, and update the page after the user dismisses a success modal.
Because the API currently requires a user ID for post creation, the tutorial temporarily hardcodes a user ID in the JavaScript to simulate a logged-in user. That scaffolding lets the front end create, edit, and delete posts immediately, including demonstrating what happens when permission checks fail for posts owned by other users. The UI relies on Bootstrap modals for three key moments: creating a post, confirming destructive actions, and displaying feedback. Two additional modals—one for success (green) and one for errors (red)—are injected into layout.html so they can be triggered from any page.
On the front-end side, a small utilities module (utils.js) centralizes two pieces of logic that matter for real API integration. First, getErrorMessage extracts user-friendly text from FastAPI error payloads, handling both simple string details and structured validation errors (arrays of error objects) by pulling out message fields and joining them. Second, showModal and hideModal wrap Bootstrap’s modal instance creation and safe hiding, so the rest of the code can focus on API calls.
The create-post flow intercepts the form submit event (preventDefault), converts FormData into a plain object, attaches the hardcoded user_id, and sends a POST request with Content-Type: application/json. When the response is OK, the code fills the success message, hides the create modal, shows the success modal, clears the form, and reloads the page after the success modal closes so the new post appears in the list. When the response is an error, it uses getErrorMessage to populate the error modal; network failures fall back to a generic “Network error” message.
A usability fix follows: posts should display newest-first. Instead of sorting in JavaScript, the tutorial updates backend queries to order by the date posted field in descending order across every endpoint that returns lists of posts (general post listing, home route listing, user-specific listing, and API user post listing). After that change, the front end automatically reflects the correct ordering because it consumes the API.
Finally, edit and delete are added. The post page already contains placeholder buttons and a delete modal; those are replaced with working Bootstrap modal triggers and forms. Edit uses a PATCH request to /api/posts/{post_id} with title and content, then shows the success modal and reloads on completion. Delete sends a DELETE request to /api/posts/{post_id}; a 204 response redirects to the homepage because the deleted post can’t remain on the detail page. Validation errors (like exceeding the title length) surface through the same getErrorMessage mechanism.
The result is a clean separation of concerns: the backend owns validation and business logic, while the front end owns presentation and interaction. The remaining security gap is explicit—hardcoded user IDs aren’t safe—so the next step is authentication with JSON web tokens, deriving user identity from the token and enforcing ownership checks server-side before allowing edits and deletes.
Cornell Notes
The tutorial connects a FastAPI JSON backend to a browser UI using Bootstrap modals and JavaScript fetch calls. A shared “Create post” modal lives in layout.html so users can add posts from any page, while success and error modals provide feedback without full-page error redirects. JavaScript intercepts form submissions, converts FormData to JSON, sends POST/PATCH/DELETE requests to the API, and reloads after success so the updated list appears. Backend queries are updated to return posts in newest-first order by ordering on the date posted field descending. Edit and delete are completed with PATCH and DELETE requests, including user-friendly handling of FastAPI validation errors via a getErrorMessage utility.
Why place the create-post modal in layout.html instead of on a single page?
How does the front end turn FastAPI validation errors into readable messages?
What request/response pattern is used for creating a post?
Why is newest-first ordering fixed on the backend rather than in JavaScript?
How do edit and delete differ at the API level?
What’s the security limitation of the current implementation?
Review Questions
- What utility function prevents raw FastAPI error objects from appearing in the UI, and how does it handle both string and array error details?
- Which backend endpoints are updated to ensure posts display newest-first, and what SQLAlchemy ordering change achieves that?
- Why does the delete handler redirect on a 204 response, while the create and edit handlers reload the page after showing a success modal?
Key Points
- 1
A create-post modal is added to layout.html so users can create posts from any page without navigating away.
- 2
JavaScript intercepts form submissions, converts FormData to JSON, and sends requests to FastAPI using fetch with Content-Type: application/json.
- 3
FastAPI validation errors are converted into readable messages via a getErrorMessage utility that handles both string and array error payloads.
- 4
Posts are sorted newest-first by updating backend SQLAlchemy queries with order_by on the date posted field in descending order across all list-returning endpoints.
- 5
Edit is implemented with a PATCH request to /api/posts/{post_id} and uses prefilled modal fields for title and content.
- 6
Delete is implemented with a DELETE request to /api/posts/{post_id}; a 204 response triggers a redirect because the post no longer exists.
- 7
Hardcoded user_id values are a temporary scaffolding and are not secure; authentication with JSON web tokens is the planned fix.