Skip to content

Course Wrap-up and Next Steps

RescueScout contains many of the patterns in a production Django site:

  • models and migrations on Postgres, with a one-to-many relationship
  • queries with the ORM, built in steps and run once
  • the admin, with groups, built-in permissions, and a custom permission
  • pages rendered from Django templates by generic views
  • a form validated with the model's rules
  • a JSON API built with Django REST Framework

The tools we used, such as uv, Ruff, djLint, and pytest, are common on Django teams today.

Takeaways

  1. Use what Django provides first.
    • The admin, generic views, and model forms cover the common cases. Write your own code where the app does something they don't.
  2. Put a field's rule on the model field.
    • The admin, model forms, and DRF's model serializers can reuse a model field's validators. A check written in one view runs only in that view.
  3. Pin versions, and run the checks before you push.
    • Commit uv.lock, so uv sync installs the package versions you tested. Upgrade on purpose: uv lock --upgrade-package django.
    • Run the tests, Ruff, and djLint locally.

What v1 Leaves Out

A production version of this site would add:

  • Accounts outside the admin: Visitors can't make accounts, and the API has no login.
  • Settings from the environment: SECRET_KEY, DEBUG, and the database password are written in config/settings.py.
  • Rules the database enforces: The approval rules run in Python, in clean() and the admin.
  • Deployment: The site runs on runserver, with DEBUG on.

What Features to Build Next

Experiment with adding to the app:

  • Logging in on the site:
    • Visitors can't make accounts, and employees and volunteers log in only through the admin. django.contrib.auth has login, logout, and password reset views. In our own views, LoginRequiredMixin requires a logged-in user, and PermissionRequiredMixin requires a permission.
  • Background work:
    • Sending an email when an application arrives, or resizing photos. Django 6.0 added a Tasks framework, django.tasks, which defines tasks and queues them through a backend. Django doesn't include the worker process that runs them; a third-party backend provides one.
  • Rules the database enforces:
    • A UniqueConstraint with a condition can refuse a second approved application for an animal, whichever way it arrives.
  • Search:
    • django.contrib.postgres adds Postgres's full-text search to the ORM, for searching descriptions as well as names.
  • A JavaScript frontend:
    • The API can serve a frontend built separately, with React or Vue, for example. On another domain or port, the API needs CORS headers, from a package such as django-cors-headers.