Use GitHub Copilot to propose Django model edits and explain migrations, then let Django generate the normal schema migration. Running makemigrations does not usually create an empty file waiting for Copilot to fill in. Replacing its operations or dependencies without understanding the migration history can break later deployments or lose data.
Official documentation checked October 14, 2026. The command examples follow Django 5.2 documentation; use the reference for your installed version. No production migration was run for this article.
How GitHub Copilot Interprets Django Model Context
Copilot can use the current editor, relevant project files, chat context, and available tools. It does not automatically know that your production schema matches your checked-in models. Give it the Django version, database engine, app label, relevant models and migration files, and a precise change request. Keep secrets and customer records out of prompts.
GitHub’s prompting guidance recommends specific requirements and relevant code. Ask for a small diff rather than a replacement of the entire models.py file. Review the suggestion before accepting it; generated code can be incorrect or insecure.
Before editing an existing project, preserve the current code and migration history in version control. Verify the environment’s database configuration without posting credentials into Chat. Development commands in this walkthrough should target an isolated development database.
Step-by-Step Workflow: Creating a Django Model with Copilot
- Open the relevant models.py file and identify whether you are adding a model or changing an existing one.
- Describe fields, allowed nulls, uniqueness, relationships, and deletion behavior. For example, ask for an optional phone field without assuming a third-party field package is installed.
- Inspect the proposed class or diff. In VS Code, Tab accepts an inline suggestion; keyboard bindings in other IDEs may differ. Reject any unrelated model replacement.
- Check imports, model inheritance, field names, validation, and Meta options against the Django field reference.
- Run the project’s existing checks and tests. Check forms, serializers, admin configuration, and code that reads or writes the changed fields.
Relationship direction matters. If each order belongs to one customer, the ForeignKey normally lives on the Order model; a field called orders on Customer would represent a different relationship. Select on_delete deliberately. CASCADE can delete related objects through Django when the referenced object is deleted; use PROTECT, RESTRICT, or another documented option when that matches the required behavior. Do not accept a generated CASCADE merely because the code imports successfully.
Generating and Reviewing Migrations with Django
Django compares model definitions with migration history when generating migrations. It does not infer ordinary model changes from the live database. Replace the example app label and migration name below with the actual values from your project.
python manage.py check
python manage.py makemigrations your_app --dry-run --verbosity 3
python manage.py makemigrations your_app
python manage.py showmigrations your_app
python manage.py sqlmigrate your_app 0002_example
python manage.py migrate --plan
The dry run previews generated files; the ordinary makemigrations command writes them. Inspect the resulting operations and dependencies instead of deleting them and asking Copilot to regenerate them. sqlmigrate shows SQL, and migrate --plan shows planned migration operations; neither proves that a large or complex change is safe. They can consult database state and should use the intended development environment.
After review, apply the migration to your isolated development database with python manage.py migrate, then test the application and relevant existing data. Repeat the deployment rehearsal in staging, confirm backup recovery, and commit the model and migration together. Production execution belongs in your reviewed release process.
Common Pitfalls and How to Avoid Them
- No migration appears: confirm the app, model changes, and migration history. An empty operations list is expected for an intentionally created empty migration, not every schema migration.
- A required or unique field is added: account for existing rows. A one-off default or uniqueness constraint may be wrong for your data. Plan separate schema and backfill steps when needed.
- Branches conflict: inspect both migration graphs and applied state. Do not guess a previous migration number, delete applied files, or use
--faketo silence an unexplained conflict. - A data migration is needed: create an intentional empty migration with
python manage.py makemigrations your_app --empty --name backfill_example. Review the RunPython logic, its dependencies, and its behavior on the correct database alias. - A reverse function is generated: verify it recovers the original data. RunPython with no reverse_code is irreversible; a no-op reverse does not restore overwritten values.
The RunPython reference requires historical models from the supplied apps registry rather than imports of the current models. Backend transaction behavior also differs. Test on the engine you deploy, and do not assume a failed MySQL schema migration can simply be rolled back.
Choose the Copilot Feature That Fits the Task
GitHub Copilot Pro is a plan; “Copilot in the IDE” is a place to use Copilot. They are not competing products. Use inline suggestions for a small field edit, and Chat to explain a migration or compare approaches. Your available models and features depend on plan, client, and organization policy; a plan does not replace Django’s migration generator.
Keep the responsibilities clear: Copilot drafts or explains, Django generates normal schema migrations, and you review and test the complete change. The GitHub responsible-use guidance leaves correctness and security review with the developer.