Backend Development: Classroom Bootcamp

An eight-hour classroom bootcamp on backend development with Python, Django, Django REST Framework and Pydantic, taught on Smarter’s code base. Smarter is a large Django project, with eighteen apps in smarter/smarter/apps/ that share one deliberately rigid layout, more than five thousand unit tests, and patterns that tutorial projects never reach: a broker layer that turns YAML manifests into database rows, Pydantic models for every manifest and contract, a Pydantic Settings class, Celery workers and a beat schedule, and caching with @cache_results. The guardrail app, the newest and cleanest, is the reference that the labs read and change. Students trace a request through it, add a field to a resource end to end, and write a management command, with tests. See Course Formats and Grading for the standard bootcamp day, the grading scale and the course policies, and Backend Development with Python, Django, Django REST Framework and Pydantic for an overview of the subject.

At a Glance

Students

Software developers who know Python and want to learn Django and the patterns of a large backend.

Deployment

Each student runs Smarter from source on their own laptop. The installation must be done and working before the bootcamp.

Cost

Free, apart from model charges when students chat with their LLMClients: less than $1 USD each with a small model.

Learning Objectives

By the end of the bootcamp, students can:

  1. Explain the request lifecycle in Django: URL routing, middleware, views, serializers, models and the ORM.

  2. Read and navigate a large Django project that follows a consistent app structure.

  3. Explain how Smarter’s broker layer turns a YAML manifest, validated by Pydantic, into database rows.

  4. Add a field to a resource end to end: Pydantic model, Django model, migration, broker and tests.

  5. Write a Django management command, and a unit test for it.

Technical Prerequisites

  • Required: Python: functions, classes and inheritance, decorators, exceptions, type hints and virtual environments.

  • Required: Git: clone, branch, commit, diff and push, and a GitHub account.

  • Required: the Linux or macOS command line: navigating directories, environment variables, running scripts.

  • Required: Docker basics: what an image and a container are, docker ps, docker logs and docker exec.

  • Required: HTTP and JSON: methods, status codes, headers, request and response bodies.

  • Required: Smarter installed from source and running, following the Developer Setup Guide. Allow an hour, and ask students to send a screenshot of docker ps beforehand.

  • Helpful: SQL and relational databases, YAML, and an editor such as Visual Studio Code with the Python extension.

Schedule

The files that the lectures refer to are listed in full under Smarter in the Source Code.

Block

Min

Content

1

45

Lecture 1: Django in one picture. Projects and apps, settings, URL routing, middleware, views, templates, models and the ORM. How Smarter’s apps in smarter/smarter/apps/ follow one rigid structure, using guardrail and secret as the examples.

2

45

Lab 1: Find your way around. Use the Django shell (python manage.py shell in the smarter-app container) to query guardrails and secrets, follow a URL to its view, and map the files of the secret app. Produces Assignment 1.

3

45

Lecture 2: APIs with Django REST Framework. Serializers, views and viewsets, authentication and permissions. Smarter’s REST API, its API key authentication and its error format.

4

45

Lab 2: Trace a request. Send an apply request with curl and an API key, then follow it through the URL route, the DRF view, the broker and the model, with log lines and a debugger. Produces Assignment 2.

5

45

Lecture 3: Pydantic and manifests. Data validation, models, field validators, and why Smarter models every manifest and API contract with Pydantic (ADR 031). The broker model.

6

45

Lecture 4: Models and migrations. Fields, relationships, Meta options, and how migrations work. Adding a field to a resource: the checklist of files it touches, and why Smarter adds a new migration, rather than regenerating 0001_initial.py, for an app that holds production data.

7

45

Lab 3: Add a field. Add an optional field to the Guardrail manifest, through the Pydantic model, Django model, migration and broker, and show it round-trip through apply and describe. Produces Assignment 3.

8

45

Lecture 5: Testing Django. Django’s test runner, Smarter’s SmarterTestBase, fixtures created once per class, cleaning up without transaction rollback, and running tests in the container.

9

45

Lab 4: Test what you built. Write tests for the new field: manifest validation, broker round trip and an invalid value. Ungraded, but leads into the capstone.

10

45

Lecture 6: Beyond the request. Management commands, Celery tasks and the beat scheduler, caching with @cache_results, and signals. Reading smarter/smarter/apps/account/management/commands/.

11

30

Capstone kickoff. Students choose a capstone, create a branch, and write a plan of the files they will change.

Smarter in the Source Code

Every lecture, lab and assignment in this course rests on the files below. Every reference is to the main branch of github.com/smarter-sh/smarter, so that students can open each one during class. Python paths are under smarter/smarter/.

One App, End to End

The guardrail app is the reference implementation that the others follow, and the one that the labs change. Every app in apps/ has the same layout.

Layer

What it does

Where to look

Django model

What is stored: fields, choices, relationships, and an ownership base class that makes every guardrail belong to an account and a user.

guardrail/models/guardrail.py, account/models/metadata_with_ownership.py

Migrations

The schema history. Smarter prefers one regenerated 0001_initial.py per app, and adds a new migration instead for released apps that hold production data.

guardrail/migrations/, smarter-migrations/SKILL.md

Pydantic manifest

What a client sends: the metadata, spec and status of a Guardrail manifest, with types, descriptions and validators. ADR 031.

guardrail/manifest/models/guardrail/

Broker

Turns the manifest into model fields (manifest_to_django_orm()) and back (django_orm_to_manifest_dict()), and implements apply, describe and delete. Smarter Broker Model.

guardrail/manifest/brokers/guardrail.py, lib/manifest/broker/abstract_broker_class.py

DRF serializer and API

Resource-style REST endpoints for guardrails and their events, beside the command-style CLI API that every kind shares.

guardrail/serializers.py, guardrail/api/v1/

Console views

The Django view and template that host the React list page, and the session-authenticated views it calls to list, clone, rename and delete.

guardrail/views/listview/, guardrail/urls.py

Signals and receivers

Events that other apps can react to, kept in signals.py and handled in receivers.py.

guardrail/signals.py, guardrail/receivers.py

Tests

One test module per source module, with test data as YAML.

guardrail/tests/

A second example

The secret app, small enough to map completely in a lab, with Fernet encryption in its model.

apps/secret/

The Request Path

Step

What happens

Where to look

URL

/api/v1/cli/apply/ and the other commands are routed to one view each.

api/v1/cli/urls.py

Authentication

The CLI API requires an API key, checked against its stored hash by a Knox-based authentication class that REST_FRAMEWORK sets as the default.

lib/drf/token_authentication.py, settings/base.py

View

The base view parses the YAML body, finds the broker for the kind, and maps every exception to a status code.

api/v1/cli/views/base.py, api/v1/cli/views/apply.py

Broker registry

A map from each kind, such as Guardrail, to its broker class.

api/v1/cli/brokers.py

Loading the manifest

YAML or JSON is parsed and checked for required keys before Pydantic validates it.

lib/manifest/loader.py

The response, and its record

Every response, success or error, is written to the journal.

lib/journal/http.py, lib/journal/models.py

Beyond the Request

Topic

What Smarter does

Where to look

Settings

Every setting is read from the environment and validated by a Pydantic Settings class. ADR 007.

common/conf/settings.py, settings/

Management commands

A SmarterCommand base class, and commands that create accounts, users and API keys, load built-in data and initialize the whole platform. ADR 010.

lib/django/management/base.py, account/management/commands/

Celery tasks and beat

Tasks on named queues, run by the worker containers, and a beat schedule that aggregates charges, evaluates budgets, purges old guardrail events and reconciles self-hosted models and vector databases. ADR 030.

workers/celery.py, workers/celerybeat.py

Caching

@cache_results builds a cache key from the function and its arguments, stores results in Redis, and can invalidate them. ADR 018.

lib/cache/decorators.py, lib/cache/lazy_cache.py

Testing

SmarterTestBase, which has no transaction rollback, so tests delete what they create, and an in-memory provider in place of every cloud call. ADR 013.

lib/unittest/base_classes.py, smarter-python-testing/SKILL.md

Adding a resource kind

The list of every file a new kind touches, from the Pydantic model to the React list page. New Feature Checklist.

smarter-sam-resource/SKILL.md

Graded Assignments

Assignment 1: App Map

Students document the structure of the secret app: what each file and folder holds, and how it connects to the rest of Smarter, and answer five questions with queries in the Django shell.

Turn in: a Markdown file in their fork with the map and the shell session.

Criterion

Pts

Exemplary

Developing

Structure

6

Every file and folder explained correctly.

Several files missing or misdescribed.

Connections

4

Shows how the app’s URLs, broker and models plug into the project.

The app is described in isolation.

Shell queries

6

All five answered with correct ORM queries.

Queries wrong or answers copied from the web console.

Clarity

4

A newcomer could use it as a guide.

Disorganized.

Assignment 2: Request Trace

Students trace one apply request from the HTTP call to the database row, and draw it as a sequence diagram, naming the file and function at each step.

Turn in: the diagram (Mermaid, PlantUML or an image) and the curl command and response.

Criterion

Pts

Exemplary

Developing

Accuracy

8

Every step correct, with file and function names.

Steps missing or out of order.

Evidence

4

Confirmed with log lines or a debugger.

Inferred from reading only.

Diagram

4

Readable, with request and response shown.

Cluttered or one-directional.

API call

4

Correct curl with an API key, and the response explained.

Incorrect call, or response unexplained.

Assignment 3: A New Field

Students add an optional field to the Guardrail resource, end to end.

Turn in: a pull request against their own fork.

Criterion

Pts

Exemplary

Developing

Completeness

8

Pydantic model, Django model, migration and broker all updated.

One layer missing, so the field is lost on the round trip.

Round trip

4

apply then describe returns the field.

Not demonstrated.

Conventions

4

Naming, docstrings and style follow the existing code; pre-commit passes.

Inconsistent with neighbors, or hooks fail.

Pull request

4

Clear description of what, why and how it was tested.

Empty or one-line description.

Capstone Projects

Students choose one. Capstones are due one week after the bootcamp, as a pull request against their own fork.

Capstone A: A Field with Validation and Tests

Learning objective. Make a complete, tested, documented change to a resource, as a professional pull request.

Students extend Assignment 3 into a feature: the new field gets validation rules (with clear error messages), is used by the code (for example a guardrail owner email that appears in the journal entry when it triggers), and is covered by tests and documentation.

What students turn in:

  • A pull request with the code, migration, tests and an update to the Guardrail page in docs/source/.

  • Passing tests for the app (python manage.py test smarter.apps.guardrail) and passing pre-commit hooks, shown in the pull request.

  • A short design note in the pull request description.

How it is graded (100 points):

Criterion

Pts

Exemplary

Developing

Correctness

25

Works end to end, including invalid input.

Works for the happy path only.

Tests

25

Validation, round trip and use are tested; the app’s tests all pass.

Few tests, or existing tests broken.

Code quality

20

Follows the app’s patterns, with docstrings and type hints.

Works, but unlike the surrounding code.

Documentation

15

The docs page explains the field, with an example.

No documentation.

Pull request

15

Clear description, small focused commits.

One large commit with no description.

Capstone B: A Management Command

Learning objective. Write an operational tool that uses the ORM safely, handles errors, and is tested.

Students write a manage.py command that a platform operator would use, for example a report of each account’s resource counts by kind, or a command that lists API keys unused for a number of days. It follows the existing commands in smarter/smarter/apps/account/management/commands/.

What students turn in:

  • A pull request with the command, its tests and a docs entry.

  • Example output from running it in the container.

How it is graded (100 points):

Criterion

Pts

Exemplary

Developing

Usefulness

15

Solves a real operator need, with sensible arguments.

A toy command.

Correctness and queries

25

Correct results, efficient queries (no query per row).

Correct, but with a query for every row.

Error handling

15

Bad arguments and empty results handled with clear messages and exit codes.

Crashes on bad input.

Tests

25

Normal, edge and error cases; fixtures cleaned up.

Happy path only, or leaves data behind.

Conventions and documentation

20

Follows the existing commands; help text and docs.

Inconsistent, undocumented.

Further Study