Zrobiłbym to za pomocą pojedynczej migracji. Najpierw programowo pobierz unikalną nazwę ograniczenia, a następnie upuść i dodaj ponownie (ponieważ zmiana wydaje się działać tylko dla ograniczeń FK, a nie dla ograniczeń unikalnych). Dodaj migrację odwrotną, która również to cofnie.
from django.db import migrations, connection
def _make_deferrable(apps, schema_editor):
"""
Change the unique constraint to be deferrable
"""
# Get the db name of the constraint
MyModel = apps.get_model('myapp', 'MyModel')
CONSTRAINT_NAME = schema_editor._constraint_names(MYModel,
['col1', 'col2'],
unique=True)[0]
TABLE_NAME = MyModel._meta.db_table
# Drop then re-add with deferrable as ALTER doesnt seem to work for unique constraints in psql
with schema_editor.connection.create_cursor() as curs:
curs.execute(
f'ALTER TABLE {TABLE_NAME} DROP CONSTRAINT "{CONSTRAINT_NAME}";'
)
curs.execute(
f'ALTER TABLE {TABLE_NAME} ADD CONSTRAINT'
f' {CONSTRAINT_NAME}'
f' UNIQUE (col1, col2) DEFERRABLE INITIALLY DEFERRED;'
)
def _unmake_deferrable(apps, schema_editor):
"""
Reverse the unique constraint to be not deferrable
"""
# Get the db name of unique constraint
MyModel = apps.get_model('myapp', 'MyModel')
CONSTRAINT_NAME = schema_editor._constraint_names(MyModel,
['col1', 'col2'],
unique=True)[0]
TABLE_NAME = MyModel._meta.db_table
with schema_editor.connection.create_cursor() as curs:
curs.execute(
f'ALTER TABLE {TABLE_NAME} DROP CONSTRAINT "{CONSTRAINT_NAME}";'
)
curs.execute(
f'ALTER TABLE {TABLE_NAME} ADD CONSTRAINT'
f' {CONSTRAINT_NAME}'
f' UNIQUE (col1, col2) NOT DEFERRABLE;'
)
class Migration(migrations.Migration):
dependencies = [
('myapp', '<previous_mig>'),
]
operations = [
migrations.RunPython(code=_make_deferrable, reverse_code=_unmake_deferrable)
]