Adding Data (POST + redirect)
Goal: Let visitors add new Todos through an HTML form. You'll meet #partial public
, #param
, #insert
, and #redirect
—the minimum write path.
Estimated time: 15 minutes.
1 What we're building
- Before:
/todos
shows a read‑only list (Part 1). - After: Typing in an input box creates a row in the
todos
table and the browser reloads the list.
2 Extend templates/todos.pageql
Add the lines after the <h1>...</h1>
and append a new public partial at the top of the file.
<!-- Add the following lines after <h1>Todos</h1> --> <form method="POST" action="/todos/add"> <input name="text" placeholder="What needs to be done?" autofocus> </form>
<form method="POST" action="/todos/add"> <input name="text" placeholder="What needs to be done?" autofocus> </form>
<!-- Add this partial at the top of the file --> {{#partial POST add}} {{#param text required minlength=1}} {{#insert into todos(text, completed) values (:text, 0)}} {{#redirect '/todos'}} {{/partial}}{{#partial POST add}} {{#param text required minlength=1}} {{#insert into todos(text, completed) values (:text, 0)}} {{#redirect '/todos'}} {{/partial}}
Save the file—your dev server is still running from Part 1 and reloads the page automatically.
3 Walk‑through
Piece | Purpose |
---|---|
<form … action="/todos/add"> |
Sends a POST request to the auto‑generated route of our public partial. |
#partial public add |
Turns a template block into an HTTP endpoint at /todos/add . |
#partial POST add |
Turns a template block into an HTTP endpoint at /todos/add . |
#param text required minlength=1 |
Validates and binds request parameters. Stops processing with a clear error if validation fails. |
#insert into |
Executes INSERT INTO todos … safely with bound params. |
#redirect '/todos' |
Finishes the request by returning 302 + Location: /todos , so the browser issues a GET and the list re‑renders. |
3.1 Request cycle in 3 steps
- Browser: POST
/todos/add
⇢ body{text="learn PageQL"}
- Server: partial
add
validates → inserts → responds 302Location: /todos
- Browser: automatically GETs
/todos
→ template reruns,#from
picks up the new row.
POST /todos/add → 302 Redirect → GET /todos
4 Try it out
- Open http://localhost:8000/todos
- Type "Feed the cat" → Enter.
- Page reloads showing your brand‑new item.
- Add a blank item—notice how validation blocks it with an error page.
(Validation errors return a plain‑text stack trace in dev mode; there's no production mode yet.)
5 Recap
- Public partials = endpoints. They keep GET pages slim by moving mutations out.
#insert
is SQL, not magic. Every column and param is explicit and bound.- The POST‑Redirect‑GET pattern prevents duplicate submissions on refresh.