generate-migration
Generates database migrations for Django-based projects efficiently.
Install
mkdir -p .claude/skills/generate-migration && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/2261" && unzip -o skill.zip -d .claude/skills/generate-migration && rm skill.zipInstalls to .claude/skills/generate-migration
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Generate Django database migrations for Sentry. Use when creating migrations, adding/removing columns or tables, adding indexes, or resolving migration conflicts.Key capabilities
- →Generates Django migration scripts for schema alterations
- →Creates empty migrations for custom data work
- →Resolves migration conflicts using lockfile updates
- →Verifies generated SQL for migration correctness
- →Tests data migrations and backfills
How it works
The skill uses Django management commands to generate migration files based on model changes. It requires manual verification of SQL and adherence to specific safety flags for deployment.
Inputs & outputs
When to use generate-migration
- →Add a new column to a database table
- →Generate migrations for model changes
- →Resolve migration conflicts in Django
About this skill
Generate Django Database Migrations
Commands
Generate migrations automatically based on model changes:
sentry django makemigrations
For a specific app:
sentry django makemigrations <app_name>
Generate an empty migration (for data migrations or custom work):
sentry django makemigrations <app_name> --empty
After Generating
- If you added a new model, ensure it's imported in the app's
__init__.py - Review the generated migration for correctness
- Run
sentry django sqlmigrate <app_name> <migration_name>to verify the SQL - Apply the migration locally with
sentry django migrate <app_name>— Sentry's migration framework runs its safety checks on apply, so this catches unsafe ops (missingis_post_deployment, unsafe column changes, etc.) before CI does.
When editing a generated migration (e.g. swapping DeleteModel for SafeDeleteModel), leave the auto-generated is_post_deployment comment block in place. It documents a non-obvious flag with concrete guidance for future migration authors — useful context, not fluff. Only remove a comment if it's stale or contradicts the code.
Don't test the ORM
Don't write tests that only exercise Django's ORM. Standard operations — create/update/delete, cascading deletes, unique-constraint enforcement — are provided by Django and Postgres and are assumed to work. Test your logic (business rules, signal receivers, custom managers/validation), not the framework's.
Do test data migrations and backfills
The exception to the above: a migration that backfills or transforms data is your logic, and it must have a test. Use the TestMigrations base class from sentry.testutils.cases; tests live in tests/sentry/migrations/.
Set app, migrate_from (the migration just before yours), and migrate_to (yours). Seed pre-migration rows in setup_before_migration(self, apps) using the historical model registry (apps.get_model("sentry", "MyModel")) — not a direct from sentry.models... import, since the current model may not match the schema at migrate_from. Then assert the post-migration state.
Write exactly one test_* method. setUp runs the full migrate-down → seed → migrate-up cycle on every test method, so each extra method pays for another round trip with no added coverage. Cover multiple cases by seeding all of them in setup_before_migration and asserting each in the single test body.
from sentry.testutils.cases import TestMigrations
class BackfillFooTest(TestMigrations):
app = "sentry"
migrate_from = "0123_before"
migrate_to = "0124_backfill_foo"
def setup_before_migration(self, apps):
Foo = apps.get_model("sentry", "Foo")
self.empty = Foo.objects.create(value=None)
self.already_set = Foo.objects.create(value="kept")
def test_backfill(self):
self.empty.refresh_from_db()
self.already_set.refresh_from_db()
assert self.empty.value == "expected"
assert self.already_set.value == "kept"
app and connection: app is the Django app label whose migration you're testing — "sentry" by default, but set it to e.g. "workflow_engine" when the migration lives in that app's migrations/ directory. connection is the database alias, "default" by default; set it to whichever connection the model's table actually lives on. Both must match where the migration and its tables actually live, or the migrate up/down will run against the wrong database.
Run these tests locally with the --migrations and --reuse-db flags. On the first run, it will be necessary to use --create-db along with --reuse-db to get the database in a good state.
Guidelines
Adding Columns
- Use
db_default=<value>instead ofdefault=<value>for columns with defaults - Nullable columns: use
null=True - Not null columns: must have
db_defaultset
Adding Indexes
For large tables, set is_post_deployment = True on the migration as index creation may exceed the 5s timeout.
Deleting Columns
- Make column nullable (
null=True) if not already - Remove all code references
- Replace
RemoveFieldwithSafeRemoveField(..., deletion_action=DeletionAction.MOVE_TO_PENDING) - Deploy, then create second migration with
SafeRemoveField(..., deletion_action=DeletionAction.DELETE)
Removing a Model (and eventually its table)
Two-phase process — the historical_silo_assignments entry must be added in phase 1.
Phase 1 — Remove the model class (MOVE_TO_PENDING)
- Remove all code references
- Replace
DeleteModelwithSafeDeleteModel(..., deletion_action=DeletionAction.MOVE_TO_PENDING) - Add the table to
historical_silo_assignmentsinsrc/sentry/db/router.py(orgetsentry/db/router.pyfor getsentry models). Pick the silo the model used — usuallySiloMode.CELL. - Deploy
Phase 2 — Drop the table (DELETE)
After phase 1 has deployed, create a second migration with SafeDeleteModel(..., deletion_action=DeletionAction.DELETE). Leave the historical entry in place — the table-drop migration relies on it to resolve the silo.
Renaming Columns/Tables
Don't rename in Postgres. Use db_column or Meta.db_table to keep the old name.
Resolving Merge Conflicts
If migrations_lockfile.txt conflicts:
bin/update-migration <migration_name>
This renames your migration, updates dependencies, and fixes the lockfile.
When not to use it
- →When testing standard ORM operations like create or update
- →When renaming columns or tables directly in Postgres
Prerequisites
Limitations
- →Requires manual review of generated migrations
- →Requires specific test classes for data backfills
- →Requires two-phase process for model deletion
How it compares
This workflow automates the generation of migration files and provides specific safety checks compared to manual script creation.
Compared to similar skills
generate-migration side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| generate-migration (this skill) | 8 | 1mo | Review | Intermediate |
| django-pro | 20 | 4mo | No flags | Intermediate |
| django-insights | 0 | 4mo | Review | Intermediate |
| sigma-audio-crm | 0 | 2mo | Caution | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by getsentry
View all by getsentry →You might also like
django-pro
sickn33
Master Django 5.x with async views, DRF, Celery, and Django Channels. Build scalable web applications with proper architecture, testing, and deployment. Use PROACTIVELY for Django development, ORM optimization, or complex Django patterns.
django-insights
carlosapgomes
Diagnóstico de saúde para projetos Django: performance, segurança e arquitetura.
sigma-audio-crm
YuvrajGaykhe
Use this skill for ALL development, debugging, review, refactoring, feature building, and integration work on the Sigma Audio Dealer & Sales Intelligence Platform. Trigger whenever the user mentions leads, dealers, follow-ups, RBAC, CRM, audit logs, Kanban pipeline, analytics, sales executive, Djang
drizzle-orm
EpicenterHQ
Drizzle ORM patterns for type branding and custom types. Use when working with Drizzle column definitions, branded types, or custom type conversions.
database-migration
wshobson
Execute database migrations across ORMs and platforms with zero-downtime strategies, data transformation, and rollback procedures. Use when migrating databases, changing schemas, performing data transformations, or implementing zero-downtime deployment strategies.
backend-dev
marmelab
Coding practices for backend development in Atomic CRM. Use when deciding whether backend logic is needed, or when creating/modifying database migrations, views, triggers, RLS policies, edge functions, or custom dataProvider methods that call Supabase APIs.