一键导入
django-migration-check
Check and validate Django migrations for safety and correctness before deployment
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Check and validate Django migrations for safety and correctness before deployment
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Configure the current project with Django 6.x expert tools (rules, skills, agents, hooks) from GitHub. Use when setting up a Django project.
Debug Django issues - ORM queries, migrations, template errors, async problems. Use when debugging Django applications.
Create a new REST API endpoint following modern DRF best practices
Create a new Django app following modern best practices and cookiecutter-django conventions
Create a new Django model following modern best practices
Analyze and optimize Django application performance
| name | django-migration-check |
| description | Check and validate Django migrations for safety and correctness before deployment |
| disable-model-invocation | true |
| allowed-tools | Read, Bash, Grep, Glob |
Run this checklist on every migration before committing. Execute each step.
# List uncommitted migration files
git status --short | grep migrations
# Or list all pending migrations
python manage.py showmigrations --list | grep "\[ \]"
For each new migration, inspect the generated SQL:
python manage.py sqlmigrate <app_name> <migration_number>
Check the SQL for:
ALTER TABLE ... ADD COLUMN ... NOT NULL without a DEFAULT — dangerous on large tablesCREATE INDEX without CONCURRENTLY on large tables — locks the tableALTER TABLE ... DROP COLUMN — data loss, ensure multi-step deployALTER TABLE ... ALTER COLUMN TYPE — may rewrite the tableALTER TABLE ... RENAME COLUMN — breaks running code during deploynull=True) or has db_default or defaultdb_default is used, verify it's supported by the databasedb_default over Python default (avoids table rewrite on older PG)BooleanField, use db_default=True/False instead of null=True.values() calls referencing this fielddb_column to keep the same column name:
new_name = models.CharField(db_column="old_name", max_length=255)
CONCURRENTLY:
class Migration(migrations.Migration):
atomic = False # Required for CONCURRENTLY
operations = [
migrations.AddIndex(
model_name="order",
index=models.Index(fields=["status"], name="orders_order_status_idx"),
),
]
%(app_label)s_%(model)s_%(field)s_idxCheckConstraint: Verify existing data satisfies the constraint
python manage.py shell -c "
from app.models import Model
violations = Model.objects.filter(amount__lt=0).count()
print(f'Violations: {violations}')
"
UniqueConstraint: Verify no existing duplicates
python manage.py shell -c "
from django.db.models import Count
from app.models import Model
dupes = Model.objects.values('user', 'slug').annotate(c=Count('id')).filter(c__gt=1)
print(f'Duplicates: {dupes.count()}')
"
migrations.RunPython.noop)apps.get_model() — never imports models directlydef populate_status(apps, schema_editor):
Order = apps.get_model("orders", "Order")
batch_size = 1000
while True:
batch = list(Order.objects.filter(status="").values_list("pk", flat=True)[:batch_size])
if not batch:
break
Order.objects.filter(pk__in=batch).update(status="draft")
# Apply the migration
python manage.py migrate <app_name> <new_migration>
# Verify the app still works
python manage.py check
pytest <app_name>/tests/ -x
# Roll back the migration
python manage.py migrate <app_name> <previous_migration>
# Verify rollback worked
python manage.py check
# Test from zero (CI should do this)
python manage.py migrate <app_name> zero
python manage.py migrate <app_name>
## Migration Review: <app_name>/<migration_file>
**Operations:**
- AddField: `status` to `Order` (CharField, db_default="draft") ✅ Safe
- AddIndex: `orders_order_status_idx` on `Order.status` ⚠️ Use CONCURRENTLY for large tables
**Risk Level:** Low / Medium / High
**Requires Multi-Step Deploy:** Yes / No
**Estimated Lock Time:** None / <1s / >1s (investigate)
**Backward Compatible:** Yes / No
**Recommendations:**
1. ...