Skip to content

Instantly share code, notes, and snippets.

@ranelpadon
Created July 6, 2022 20:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ranelpadon/07922a098187c787e63925e24df56c5b to your computer and use it in GitHub Desktop.
Save ranelpadon/07922a098187c787e63925e24df56c5b to your computer and use it in GitHub Desktop.
Prevent "duplicate table/column" errors when running migrations due to a similarly named, previously ran migration
"""
manage.py sync_migrations
"""
import re
from django.core.management.base import BaseCommand
from django.db import (
DEFAULT_DB_ALIAS,
connections,
)
from django.db.migrations.loader import MigrationLoader
from django.db.migrations.recorder import MigrationRecorder
class Command(BaseCommand):
def handle(self, *args, **options):
connection = connections[DEFAULT_DB_ALIAS]
Migration = MigrationRecorder.Migration
loader = MigrationLoader(connection, ignore_no_migrations=True)
migrations_done = []
migrations_pending = 0
for app, migration_candidate in loader.disk_migrations:
if (app, migration_candidate) not in loader.applied_migrations:
# Strip the migration numbers.
migration_name = re.sub(r'[\d]+_', '', migration_candidate, 1)
# Check if a similarly named migration were already ran before.
migration_is_done = Migration.objects.filter(name__endswith=migration_name).exists()
if migration_is_done:
print('This migration is done: {} {}'.format(app, migration_candidate))
# Create new migration entry in `django_migrations` table,
# which includes the new migration number.
new_migration = Migration(
app=app,
name=migration_candidate,
)
migrations_done.append(new_migration)
else:
migrations_pending += 1
Migration.objects.bulk_create(migrations_done)
print('Summary')
print('=' * 10)
print('Total:', len(loader.disk_migrations))
print('Done:', len(migrations_done))
print('Pending:', migrations_pending)
if migrations_pending:
print('=' * 20)
print('Run `manage.py migrate` to complete the pending migrations')
print('=' * 20)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment