Django from Basics to Production · Capstone

Capstone: An Event Ticketing App in Django

Design a Django and DRF app for selling event tickets: models, API, concurrency, permissions, tests and deployment.

Create a free account to save this page, take notes and track your progress. Sign in

Scenario

A small events company sells tickets for 20 to 50 events a month. Organisers create events and ticket types with limited quantities; customers buy tickets on the website and in a mobile app. Popular events sell out in minutes.

Requirements

  • Never sell more tickets than available, even when hundreds of people buy at once.
  • Organisers manage only their own events; customers see only their own orders.
  • A confirmation email after each successful purchase.
  • An admin view for support staff.

Constraints

  • Django 6.1, DRF, PostgreSQL, Redis available.
  • Deployed as containers behind a load balancer with TLS.

Deliverables

  1. Models and relationships.
  2. API design with serializers, viewsets and permissions.
  3. Concurrency for ticket sales.
  4. Testing strategy.
  5. Deployment settings and process.

Hints

  • The database is the place to enforce limits.
  • Emails must not be sent for purchases that didn't happen.

Draft each deliverable below before revealing the model answer and rubric.

Further reading: Django documentation · Django REST framework

Deliverables

Describe the models.

Model answer

  • Event(organiser FK User, title, starts_at, venue), TicketType(event FK, name, price Decimal, quantity, sold) with a database CheckConstraint(sold <= quantity).
  • Order(customer FK User, created_at, status) and OrderItem(order FK, ticket_type FK, quantity).
  • Indexes on Event.starts_at and foreign keys used in filters; PROTECT on ticket types with sold tickets.

Rubric

Look for a sold counter protected by a database constraint, Decimal prices and sensible deletion rules.

Describe the API.

Model answer

  • Public read-only EventViewSet (list with pagination, filters by date); organiser ManageEventViewSet with get_queryset filtered to organiser=request.user and owner set in perform_create.
  • OrderViewSet for customers: create and list own orders only.
  • Serializers with explicit fields, read-only status and totals, validation of quantities (1 to 10 per order).

Rubric

Strong answers scope querysets per user, set owners server-side and keep validation in serializers.

How do you prevent overselling?

Model answer

  • In transaction.atomic(): create the order, then TicketType.objects.filter(pk=..., sold__lte=F("quantity") - qty).update(sold=F("sold") + qty); zero rows updated means sold out, so raise and roll back.
  • The check constraint is a second line of defence.
  • Confirmation emails queued with transaction.on_commit to a Celery or RQ worker.

Rubric

Look for an atomic conditional update or row locking inside a transaction, plus on_commit for side effects.

Describe testing.

Model answer

  • TestCase with setUpTestData for events and users; API tests for permissions (organiser A can't edit B's event, customers can't see others' orders).
  • A concurrency test with TransactionTestCase and threads (against PostgreSQL) buying the last tickets: exactly the available number succeed.
  • assertNumQueries on event lists and order history; check --deploy in CI.

Rubric

Strong answers include permission tests, a real concurrency test on PostgreSQL and query-count assertions.

Describe deployment.

Model answer

  • Settings from the environment: DEBUG off, SECRET_KEY, ALLOWED_HOSTS, DATABASE_URL; HTTPS settings with SECURE_PROXY_SSL_HEADER for the load balancer.
  • Gunicorn (or uvicorn for ASGI) in a non-root container; static files via collectstatic and WhiteNoise or a CDN.
  • Migrations run as a release job before new containers receive traffic; health endpoint; JSON logging; the Django admin restricted to staff over HTTPS.

Rubric

Look for environment-driven settings, a production server, static file handling, migrations as a release step and secured admin.

Open in the app to mark lessons complete, take notes and track your progress.

Was this page helpful?