
Creating Forms and Handling POST Requests in Flask | Python Comeback Journey #9
At this point, my Flask app could read data from a JSON file, but it couldn’t add anything new without me editing that file manually. I wanted the app to feel alive — to let users (or me) submit new books directly from the browser.
That meant learning how to build a form and handle a POST request.
🧩 Step 1: Building the Form
I started by creating a new file called add_book.html inside the templates/ folder. It extended base.html just like the others but contained a simple HTML form:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
{% extends “base.html” %} {% block title %}Add New Book – Book Tracker{% endblock %} {% block content %} <form method=“POST” action=“{{ url_for(‘add_book’) }}”> <label for=“title”>Title:</label> <input type=“text” id=“title” name=“title”> <label for=“author”>Author:</label> <input type=“text” id=“author” name=“author”> <label for=“status”>Status:</label> <input type=“text” id=“status” name=“status”> <button type=“submit”>Add Book</button> </form> {% endblock %} |
It wasn’t pretty (yet), but it worked. I could type a book title, author, and status, and hit Add Book.
⚙️ Step 2: Handling POST Requests in Flask
In app.py, I added this route:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
@app.route(‘/add’, methods=[‘GET’, ‘POST’]) def add_book(): if request.method == ‘POST’: title = request.form[‘title’] author = request.form[‘author’] status = request.form[‘status’] # Read existing books with open(‘data/books.json’, ‘r’) as f: books = json.load(f) # Generate next ID max_id = max((book[‘id’] for book in books), default=0) # Create new book entry new_book = { ‘id’: max_id + 1, ‘title’: title, ‘author’: author, ‘status’: status } # Add and save back books.append(new_book) with open(‘data/books.json’, ‘w’) as f: json.dump(books, f, indent=4) flash(‘Book added successfully!’) return redirect(url_for(‘home’)) # If GET request, show empty form return render_template(‘add_book.html’) |
It may look long, but each part has a purpose:
request.formgrabs the input values from the form.json.load()/json.dump()handle reading and saving data.flash()shows a success message.redirect(url_for('home'))returns the user to the main list after adding the book.
When everything worked, I saw a small popup message — “Book added successfully!” — confirming that the app now accepted input and stored it persistently.
💡 Step 3: Lessons Learned
Before this, every change to my book list required editing JSON by hand. Now, I could do it from the browser. The app had gone from static to interactive.
But the real lesson was about how Flask processes web forms:
- GET requests retrieve data (like showing the form),
- POST requests send data (like submitting it).
Understanding that duality changed how I thought about the web itself — every button click, every form submission is really just a structured conversation between the browser and the server.
🚀 Reflection
The /add route felt like a small victory. My Flask app could now grow on its own, one book at a time.
It also set the stage for a deeper topic I ran into next: why new data didn’t always show up instantly and how Flask’s internal state works.
Stay tuned for Python Comeback Journey #10: When Data Doesn’t Refresh — Understanding Flask’s State and Persistence.





Leave a Reply