Get AI summaries of any video or article — Sign up free
Python FastAPI Tutorial (Part 9): Frontend Forms - Connecting JavaScript to Your API thumbnail

Python FastAPI Tutorial (Part 9): Frontend Forms - Connecting JavaScript to Your API

Corey Schafer·
5 min read

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.

TL;DR

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?

Putting the modal in the base layout makes the form available from anywhere in the app (homepage, individual post pages, and other pages). It also keeps users on their current page because opening a modal doesn’t require navigation. That matters once the same CRUD actions need to be reachable across multiple routes.

How does the front end turn FastAPI validation errors into readable messages?

FastAPI validation errors can arrive as structured data (often an array of error objects) rather than a single string. The getErrorMessage utility checks whether detail is a string; if so, it returns it directly. If detail is an array, it extracts each error object’s message field and joins them into one user-friendly string, preventing raw object dumps from leaking into the UI.

What request/response pattern is used for creating a post?

On submit, JavaScript calls event.preventDefault, builds a plain object from FormData, adds a temporary hardcoded user_id, and sends fetch to the API with method: 'POST' and headers: { 'Content-Type': 'application/json' }. On an OK response, it parses JSON, fills the success modal message, hides the create modal, shows the success modal, clears the form, and reloads after the success modal closes. On error, it parses the error payload, fills the error modal, and shows it; network failures trigger a generic network error message.

Why is newest-first ordering fixed on the backend rather than in JavaScript?

Sorting in JavaScript would be less efficient and inconsistent across clients. The tutorial updates backend queries to order by the date posted field descending using SQLAlchemy order_by, so every client receives the same ordering. It applies this change across all endpoints that return lists of posts, ensuring consistent behavior on home listings, user-specific listings, and API routes.

How do edit and delete differ at the API level?

Edit uses PATCH to /api/posts/{post_id} because it’s a partial update (title and content only, not user_id). Delete uses DELETE to /api/posts/{post_id} with no request body because the post_id in the URL identifies the resource. A successful delete returns HTTP 204, and the UI redirects to the homepage since the deleted post can’t be displayed.

What’s the security limitation of the current implementation?

The API requires a user ID for create/edit/delete, but the tutorial temporarily hardcodes user_id in JavaScript. That means anyone could call the API directly and modify posts without proper authorization. The next tutorials plan to replace this with authentication using JSON web tokens and server-side ownership checks.

Review Questions

  1. What utility function prevents raw FastAPI error objects from appearing in the UI, and how does it handle both string and array error details?
  2. Which backend endpoints are updated to ensure posts display newest-first, and what SQLAlchemy ordering change achieves that?
  3. 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. 1

    A create-post modal is added to layout.html so users can create posts from any page without navigating away.

  2. 2

    JavaScript intercepts form submissions, converts FormData to JSON, and sends requests to FastAPI using fetch with Content-Type: application/json.

  3. 3

    FastAPI validation errors are converted into readable messages via a getErrorMessage utility that handles both string and array error payloads.

  4. 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. 5

    Edit is implemented with a PATCH request to /api/posts/{post_id} and uses prefilled modal fields for title and content.

  6. 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. 7

    Hardcoded user_id values are a temporary scaffolding and are not secure; authentication with JSON web tokens is the planned fix.

Highlights

The UI uses Bootstrap modals plus fetch-based JSON requests to deliver full CRUD from the browser, including success and error feedback without redirecting to error pages.
Backend ordering is corrected with SQLAlchemy order_by(date_posted, descending) so every client sees newest posts first—no client-side sorting needed.
Edit uses PATCH for partial updates, while delete relies on DELETE and a 204 response to redirect away from a now-missing post.
A dedicated error-message utility turns FastAPI’s structured validation payloads into clean, user-friendly text.

Topics

  • FastAPI CRUD
  • Bootstrap Modals
  • JavaScript Fetch
  • Form Validation
  • SQLAlchemy Ordering

Mentioned