Mock Data
Mock Data
Sección titulada «Mock Data»Local development boots into a fully populated database from two Django fixtures, loaded with manage.py loaddata. There are no seed_* management commands — they were removed in favour of native fixtures.
[!info] Authority Mock-data scope (what is allowed where) lives in [[adr-022-mock-data-scope|ADR-022]]. This page is the operational workflow.
The two fixtures
Sección titulada «The two fixtures»Location: backend/fixtures/. Format: Django’s native serialized YAML (dumpdata --format=yaml). Chosen over per-app fixtures/ dirs so the whole dataset lives in one obvious place and the two files load in a fixed, explicit order.
| File | Contents | Records |
|---|---|---|
mock_clinic.yaml | Everything except employees: mock users, org units, positions, tag catalog, position tags | 90 |
mock_employees.yaml | Only employee-scoped data: employees + their tags, assignments, transition logs, tag-change logs | 266 |
Per-model breakdown:
| Model | Fixture | Count |
|---|---|---|
users.User (5 mock users, no superuser) | mock_clinic | 5 |
demand.OrgUnit | mock_clinic | 25 |
demand.Position | mock_clinic | 14 |
tags.TagCatalog | mock_clinic | 23 |
tags.PositionTag | mock_clinic | 23 |
api.Employee | mock_employees | 35 |
tags.EmployeeTag | mock_employees | 90 |
assignments.Assignment | mock_employees | 18 |
fsm.EmployeeTransitionLog | mock_employees | 33 |
tags.TagChangeLog | mock_employees | 90 |
Loading flow
Sección titulada «Loading flow»On every boot, backend/entrypoint.sh step [3/6] runs (local settings only):
python manage.py loaddata fixtures/mock_clinic.yamlpython manage.py loaddata fixtures/mock_employees.yamlTo load manually on a fresh instance, run the same two commands inside the container in that order.
FK ordering
Sección titulada «FK ordering»mock_clinic.yaml loads first because every employee-scoped row in mock_employees.yaml has a foreign key into it:
EmployeeTag/TagChangeLog→TagCatalog,UserAssignment→PositionEmployeeTransitionLog→User(actor)
Within mock_employees.yaml, Employee is serialized before the rows that reference it. The superuser is excluded from the fixtures — it is created separately by create_superuser ([[admin|Admin]]) and is never referenced as a FK target by mock data.
[!important]
TagChangeLogand therawguardTagChangeLogrows are audit records normally auto-created by apost_savesignal onEmployeeTag([[adr-019-tag-based-requirements|ADR-019]] §11). The signal inapps/tags/signals.pynow skips whenraw=True, which is the flag Django sets duringloaddata. This makes loading idempotent: the 90TagChangeLogrows come straight from the fixture, and re-runningloaddata(e.g. on container restart) does not duplicate them.
Idempotency
Sección titulada «Idempotency»Fixtures carry explicit UUID primary keys, so loaddata upserts by PK. Re-running it on a populated DB overwrites rows with identical data — no duplicates, no growth. The entrypoint can therefore re-load on every restart safely.
Regenerating the fixtures
Sección titulada «Regenerating the fixtures»When you change the dataset (add an employee, a tag, etc.), regenerate from a live DB:
# 1. Boot a clean, fully-loaded DBdocker compose down -v && docker compose up -d
# 2. (apply your edits via the admin/API/shell so they land in the DB)
# 3. Dump back into the two files, respecting the splitdocker compose exec api python manage.py dumpdata --format=yaml --indent 2 \ users.User --pks=<comma-separated mock-user PKs> \ > backend/fixtures/_users.partdocker compose exec api python manage.py dumpdata --format=yaml --indent 2 \ demand.OrgUnit demand.Position tags.TagCatalog tags.PositionTag \ > backend/fixtures/_rest.partcat backend/fixtures/_users.part backend/fixtures/_rest.part > backend/fixtures/mock_clinic.yamlrm backend/fixtures/_users.part backend/fixtures/_rest.part
docker compose exec api python manage.py dumpdata --format=yaml --indent 2 \ api.Employee tags.EmployeeTag assignments.Assignment fsm.EmployeeTransitionLog tags.TagChangeLog \ > backend/fixtures/mock_employees.yaml[!note] Exclude the superuser Dump
users.Userwith--pks=limited to the 5 mock users (is_superuser=False). Get them with:python manage.py shell -c "from apps.users.models import User; print(','.join(str(p) for p in User.objects.filter(is_superuser=False).values_list('id', flat=True)))"
Verify a clean boot loads purely from the fixtures:
docker compose down -v && docker compose up -ddocker compose logs api | grep "Installed" # → 90 + 266 objectsRelationship to the frontend showcase
Sección titulada «Relationship to the frontend showcase»The frontend showcase has its own, separate mock dataset at frontend/src/app/shared/mocks/clinic-bienestar.json (the showcase SSOT per [[adr-022-mock-data-scope|ADR-022]]). It is consumed directly by /showcase components without the API and is not generated from, nor coupled to, these backend fixtures. The two share the Clínica Bienestar scenario and aligned deterministic UUIDs, but each is maintained independently. Do not delete or regenerate one from the other.