Backend Challenges
Try these after completing all 6 backend steps.
Knowledge Check
-
What does
jsonify()do in Flask? Why can't you return a plain dictionary? -
What is the purpose of a virtual environment?
-
What does
db.session.commit()do? What happens if you forget to call it? -
What does the
nullable=Falseparameter mean in a database column? -
Why should you never commit
.envfiles to git?
Code Challenges
Challenge 1: Add a DELETE Endpoint
The backend already has a /api/messages/<id> DELETE route in routes.py. Add a DELETE ALL endpoint that clears all messages:
DELETE /api/messages
It should delete every message from the database and return {"deleted": count}.
Challenge 2: Add a System Prompt Route
Create a new endpoint that lets you change the AI's personality without restarting the server:
POST /api/system-prompt
Body: {"prompt": "You are a pirate who speaks in riddles."}
GET /api/system-prompt
Returns: {"current_prompt": "..."}
Store the current system prompt in-memory (a variable) or in a new database table.
Challenge 3: Test the DELETE Endpoint
Write a test file tests/test_delete.py that:
1. Tests deleting a message that exists
2. Tests deleting a message that doesn't exist (404)
3. Tests that after deleting, the message list is shorter
def test_delete_reduces_message_count(client):
client.post("/api/chat", json={"message": "A"})
client.post("/api/chat", json={"message": "B"})
msgs = client.get("/api/messages").get_json()
assert len(msgs) == 2
client.delete(f"/api/messages/{msgs[0]['id']}")
remaining = client.get("/api/messages").get_json()
assert len(remaining) == 1
Challenge 4: Chat History Context
Currently, the backend only sends the latest user message to OpenAI. Modify the chat endpoint to send the last 10 messages as conversation history. This lets the AI remember context.
Hint: Query the last 10 messages from the database and format them as a messages array.
Challenge 5: Add a Custom Metric
Add a metric that tracks the average response time of the /api/chat endpoint. Hint: use time.time() before and after the OpenAI call, and store the durations in a list.
Challenge 6: Lint Your Tests
Run ruff check backend/tests/. Fix any issues ruff finds. This ensures your test code is as clean as your production code.
Open-Ended Project: Todo List API
Build a complete Todo List API from scratch:
Requirements:
POST /api/todos — Create a todo (body: {"title": "..."})
GET /api/todos — List all todos
PUT /api/todos/<id> — Mark as complete (body: {"completed": true})
DELETE /api/todos/<id> — Delete a todo
Database model:
class Todo(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(200), nullable=False)
completed = db.Column(db.Boolean, default=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
Stretch goals:
- Add a POST /api/todos/bulk that creates multiple todos at once
- Add filtering: GET /api/todos?completed=true
- Add sorting: GET /api/todos?sort=created_at&order=desc
Test with curl:
curl -X POST http://localhost:5000/api/todos \
-H "Content-Type: application/json" \
-d '{"title": "Learn Flask"}'