bhylu.com

Advertisements

Django Schema Changes

Test a migration against an earlier database state, not only an empty new database. Existing rows are where an unsafe default or rename becomes visible.

How it works

MigrationExecutor can move a disposable database to a chosen state. Use its historical app registry when working with models from that state; the current model may expect columns that do not exist yet. The listing rolls only the private in-memory workshops schema back to migration one, then reapplies the access-note migration and checks a pre-existing venue. Never use this demonstration as permission to roll back a production database.

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.

Example

Run .venv\Scripts\python.exe lessons\schema-changes.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.

lessons/schema-changes.py — core code

from django.db import connection
from django.db.migrations.executor import MigrationExecutor
executor = MigrationExecutor(connection)
executor.migrate([("workshops", "0001_initial")])
old_apps = executor.loader.project_state([("workshops", "0001_initial")]).apps
old_venue = old_apps.get_model("workshops", "Venue")
print(old_venue.objects.get(code="river-hall").name)
MigrationExecutor(connection).migrate([("workshops", "0002_venue_access_note")])
print(Venue.objects.get(code="river-hall").access_note == "")

Expected result

River Hall
True

The venue survives and receives the declared empty value for its optional note. The test exercises a real forward schema transition rather than merely inspecting a migration filename. Historical models are essential during data migrations too.

Use Django’s versioned official documentation for exact API contracts and the deployment checklist before a separate release.

Advertisements