Django Ownership Validation Exercise
A forged request claims to belong to another user. Repair the workflow by deriving identity from the authenticated session and ignoring an untrusted owner field.
Your brief
The endpoint uses request.user when calling the booking service. It never accepts a posted user primary key as authority. Try this exercise before opening the worked solution, then explain why a hidden form field provides no additional trust. The database stores the current user even when the body contains someone else’s identifier. A correct interface should also make it clear which signed-in account is acting.
Run in the supplied local Django project
This lesson uses Django 5.2.18 LTS with Python 3.12. Download the source downloader and run node download-project.mjs http://127.0.0.1:8000 with Node 22 while previewing locally. It creates a new bhylu-django-lab folder and refuses to overwrite an existing one. After deployment, the default base is bhylu.com; until then use your local preview URL.
Inside that new folder, create a virtual environment, install requirements.txt and run the complete lesson file shown below. Every lesson creates a fresh in-memory SQLite database and temporary upload storage. It does not edit the interactive lab’s db.sqlite3 or Bhylu’s database. The visible listing below is the lesson’s core code; its complete downloaded file includes the shared bootstrap.
Django does not run in Bhylu’s current browser playground. No Apache, MySQL or global PHP configuration change is needed. See the setup lesson for the full project and commands.
Worked solution
Run .venv\Scripts\python.exe lessons\exercises.py from the downloaded project root. Download the complete lesson file; keep it under lessons/. The project’s shared models, forms, views and fixture are prerequisites, not a hidden online runtime.
Show the worked solution
from django.contrib.auth import get_user_model
users = get_user_model().objects
alex, jay = users.get(username="alex"), users.get(username="jay")
client = Client()
client.force_login(alex)
response = client.post("/workshops/lamp-care/book/", {"seats":1, "user":jay.pk})
print(response.status_code)
print(Reservation.objects.get().user.username)
Expected result
302 alex
The server assigns Alex from the session rather than Jay from the request body. This is a concrete ownership-boundary test. The same principle applies when a client supplies price, role, publication state or an account identifier.
Extend and test
Repeat with a different user id and an extra published=true field. Confirm that the endpoint accepts only its declared seat input and derives all sensitive values server-side.
Use Django’s versioned official documentation for exact API contracts and the deployment checklist before a separate release.