Create - Sending Data
You know GET fetches data. POST sends data. Now let's wire up a form so that clicking a button sends a new patient to Flask, Flask saves it to PookieDB, and the table updates - all without reloading the page.
What travels in a POST request
When you send a GET request, the URL carries everything the server needs. When you send a POST request, the data travels in the request body - a separate part of the request that is not visible in the URL.
The body is always a string. To send a JavaScript object as the body, you convert it to a JSON string first using JSON.stringify():
let data = { name: "Alice", age: 24 }
JSON.stringify(data)
// '{"name":"Alice","age":24}'
That string is what travels over the network.
Telling Flask the body is JSON
When Flask receives a request, it does not automatically know what format the body is in. You tell it by setting the Content-Type header:
headers: { "Content-Type": "application/json" }
This tells Flask: "the body is a JSON string, please parse it for me."
On the Flask side, request.get_json() reads the body and converts it back to a Python dictionary.
The complete flow
JavaScript - the form and the fetch call:
function addPatient() {
let name = document.getElementById("name").value
let age = document.getElementById("age").value
fetch("/patients", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: name, age: parseInt(age) })
})
.then(response => response.json())
.then(result => {
console.log("Saved with id:", result.id)
loadPatients()
})
.catch(error => console.log("Error:", error))
}
Flask - the route that receives the POST:
@app.route('/patients', methods=['POST'])
def add_patient():
data = request.get_json()
patient = Patient.objects.create(
name=data["name"],
age=data["age"]
)
return jsonify({ "status": "ok", "id": str(patient.id) })
str(patient.id) converts the UUID object to a string so it can travel in JSON.
The complete project files
database.py
import pookiedb
pookiedb.connect("sqlite:///patients.sqlite3")
class Patient(pookiedb.Model):
id = pookiedb.UUIDField(auto=True, primary_key=True)
name = pookiedb.CharField(max_length=100)
age = pookiedb.IntegerField()
class Meta:
db_table = "patients"
Patient.create_table()
app.py
from flask import Flask, render_template, request, jsonify
from database import Patient
app = Flask(__name__)
@app.route('/')
def home():
return render_template('index.html')
@app.route('/patients', methods=['POST'])
def add_patient():
data = request.get_json()
patient = Patient.objects.create(name=data["name"], age=data["age"])
return jsonify({ "status": "ok", "id": str(patient.id) })
if __name__ == '__main__':
app.run(debug=True)
templates/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Patients</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-4">
<h1 class="mb-4">Patients</h1>
<div class="mb-3">
<input id="name" type="text" class="form-control mb-2" placeholder="Name">
<input id="age" type="number" class="form-control mb-2" placeholder="Age">
<button onclick="addPatient()" class="btn btn-primary">Add Patient</button>
</div>
<table class="table table-striped">
<thead><tr><th>Name</th><th>Age</th></tr></thead>
<tbody id="patient-rows"></tbody>
</table>
</div>
<script>
function addPatient() {
let name = document.getElementById("name").value
let age = document.getElementById("age").value
fetch("/patients", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: name, age: parseInt(age) })
})
.then(response => response.json())
.then(result => {
console.log("Saved with id:", result.id)
loadPatients()
})
.catch(error => console.log("Error:", error))
}
function loadPatients() {
// we will fill this in on the next page
}
</script>
</body>
</html>
Challenge
Set up the project exactly as shown. Run it, add a patient, and check the browser console. You should see "Saved with id:" followed by a UUID. Then stop Flask, restart it, and check whether the patient is still in the database.