This guide will help you tackle the Backend Development section of your assessment task.
We'll cover database integration, routing and request handling, and query implementation using Flask and SQLAlchemy.
In app.py, we have the following code:
Import necessary modules:
from flask import Flask
from models import db
from views import init_routes
Create a Flask application instance:
app = Flask(__name__)
Configure the database:
app.config['SECRET_KEY'] = 'dev'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///collection.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
Initialise SQLAlchemy and our routes:
db.init_app(app)
init_routes(app)
Run the app and create the database tables:
if __name__ == '__main__':
with app.app_context():
db.create_all()
app.run(debug=True)
To keep things organised, routes (or views) are placed in views.py instead of cluttering the app.py.
In views.py, define the routes for your CRUD operations:
from flask import render_template, request, redirect, url_for, flash
from models import db, YourModel
Ensure you import the name of your database model.
Below are the basic route definitions for handling Create, Read, Update, and Delete (CRUD) operations. It's up to you to implement the logic for each route based on what you've learned so far. We will look at this further in the next section. For now, we just want the simplest possible implementation to make sure it's all working. We can test it all with a very simple HTML file (included) below.
Create (POST)
@app.route('/add', methods=['POST'])
def create_item():
# This route should handle adding a new item to the database.
return render_template('index.html', message='Item added successfully')
Read (GET)
@app.route('/', methods=['GET'])
def get_items():
# This route should retrieve all items from the database.
# Query the database to get all items and return them, formatted as a list of dictionaries.
return render_template('index.html', message='Displaying all items')
Update (POST)
@app.route('/update', methods=['POST'])
def update_item():
# This route should handle updating an existing item identified by the given ID.
return render_template('index.html', message=f'Item updated successfully')
Delete (POST)
@app.route('/delete', methods=['POST'])
def delete_item():
# This route should handle deleting an existing item identified by the given ID.
return render_template('index.html', message=f'Item deleted successfully')
To help test your routes, you can use the following index.html for submitting data and interacting with your routes from a browser.
It assumes you have ID and name in your database model. Make any changes necessary.
You should see a message at the top based on which route you have used.
It is important to build apps like this up one small step at time and continually check everything is working. This is a way to check our routes work before adding in database queries and devloping UI.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CRUD Operations</title>
</head>
<body>
<h1>Items</h1>
<!-- Display any message passed from the backend -->
{% if message %}
<p><strong>{{ message }}</strong></p>
{% endif %}
<!-- This will later display items from the database -->
<ul>
<li>Sample Item 1</li>
<li>Sample Item 2</li>
</ul>
<h2>Create Item</h2>
<!-- Form to create a new item, posts to /add -->
<form action="/add" method="POST">
<input type="text" name="name" placeholder="Item Name" required>
<button type="submit">Create</button>
</form>
<h2>Update Item</h2>
<!-- Form to update an existing item, posts to /update/<id> -->
<form action="/update" method="POST">
<input type="number" name="id" placeholder="Item ID" required>
<input type="text" name="name" placeholder="New Name" required>
<button type="submit">Update</button>
</form>
<h2>Delete Item</h2>
<!-- Form to delete an existing item, posts to /delete/<id> -->
<form action="/delete" method="POST">
<input type="number" name="id" placeholder="Item ID" required>
<button type="submit">Delete</button>
</form>
</body>
</html>
The next step is to begin implementing your SQLAlchemy queries in each route. Ensure each one is working before adding any extra complexity to the index page or before adding additional routes. Here is an example of what you might try first:
views.py - READ Route
@app.route('/', methods=['GET'])
def get_items():
items = YourModel.query.all()
return render_template('index.html', message='Displaying all items', items=items)
index.html - List of Items
<ul>
{% for item in items %}
<li>{{ item.title }}</li>
{% endfor %}
</ul>
What to do: Extract the item name from the request form. Create and commit a new item to the database. E.g.
name = request.form.get('name') # Get the item name from form
new_item = YourModel(name=name) # Create new item
db.session.add(new_item) # Add to session
db.session.commit() # Commit changes
What to do: Fetch the item by its ID. Update the item’s name and commit the changes. E.g.
id = request.form.get('id') # Get the item ID from form
item = YourModel.query.get(id) # Fetch item by ID
item.name = request.form.get('name') # Update name
db.session.commit() # Commit changes
What to do: Fetch the item by its ID. Delete the item and commit the transaction. E.g.
id = request.form.get('id') # Get the item ID from form
item = YourModel.query.get(id) # Fetch item by ID
db.session.delete(item) # Delete item
db.session.commit() # Commit changes