Backend Challenges

Try these after completing all 6 backend steps.


Knowledge Check

  1. What does jsonify() do in Flask? Why can't you return a plain dictionary?

  2. What is the purpose of a virtual environment?

  3. What does db.session.commit() do? What happens if you forget to call it?

  4. What does the nullable=False parameter mean in a database column?

  5. Why should you never commit .env files 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"}'