The routes ask for an operation. The database module carries it out.
Gregory S. DeLozier, PhD
A named operation hides the details of carrying it out.
The route asks for a pet. The module handles the query.
Query details can change while the calling code stays the same.
Single Responsibility Principle (SRP): one reason to change.
| What changes? | Where it belongs |
|---|---|
| Request handling or page selection | app.py |
| How pets are stored or retrieved | database.py |
Keep code that changes for the same reason together.
http://127.0.0.1:5000/list
Separate database setup: python3 setup_database.py
app.py |
database.py |
|---|---|
| Read the request | Open the database |
| Call an operation | Execute SQL |
| Render a template | Return records |
| Choose a redirect | Commit writes |
| Function | Result |
|---|---|
get_pets() |
List of dictionaries |
get_pet(id) |
Dictionary or None |
create_pet(data) |
Saved new record |
update_pet(id, data) |
Saved changes |
delete_pet(id) |
Removed record |
| Pet fields | |
|---|---|
| Identity | id, name |
| Description | type, age |
| Care | food, owner |
pet['food'] and pet['owner'] identify
fields directly.
@app.route("/pets", methods=["GET"])
@app.route("/list", methods=["GET"])
def get_pets():
return render_template(
"list.html", pets=database.get_pets()
)The template chooses the displayed field order.
@app.route("/create", methods=["POST"])
def post_create():
database.create_pet(dict(request.form))
return redirect(url_for("get_pets"))The database function commits before returning.
create_petcursor.execute(
"INSERT INTO pet(name, age, type, food, owner) "
"VALUES (?,?,?,?,?)",
(data["name"], data["age"], data["type"],
data["food"], data["owner"]),
)
connection.commit()The column list determines the parameter order.
cursor.execute("SELECT * FROM pet WHERE id = ?", (id,))
pet = cursor.fetchone()
if pet is None:
return None
return dict(pet)A dictionary means found. None means absent.
<input name="food" value="{{data['food'] or ''}}"/>
<input name="owner" value="{{data['owner'] or ''}}"/>The form submits to /update/{{data['id']}}.
Five replacement values, followed by the identifier.
@app.route("/delete/<int:id>", methods=["GET"])
def get_delete(id):
database.delete_pet(id)
return redirect(url_for("get_pets"))The database function deletes and commits.
The tests use test_pets.db.
Route: What operation does this request ask for?
Database function: Which values and statement carry it out?
Response: How does the browser show the result?
Use the function boundary to follow one operation at a time.