Skip to content

Commit fc16015

Browse files
charettestimgraham
authored andcommitted
Fixed #26906 -- Reduced alter together operations code duplication.
Thanks Akshesh Doshi for the initial patch.
1 parent 8e3f22f commit fc16015

File tree

1 file changed

+30
-60
lines changed

1 file changed

+30
-60
lines changed

django/db/migrations/operations/models.py

Lines changed: 30 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -491,22 +491,23 @@ def reduce(self, operation, app_label=None):
491491
return super().reduce(operation, app_label=app_label)
492492

493493

494-
class AlterUniqueTogether(FieldRelatedOptionOperation):
495-
"""
496-
Change the value of unique_together to the target one.
497-
Input value of unique_together must be a set of tuples.
498-
"""
499-
option_name = "unique_together"
494+
class AlterTogetherOptionOperation(FieldRelatedOptionOperation):
495+
option_name = None
500496

501-
def __init__(self, name, unique_together):
502-
unique_together = normalize_together(unique_together)
503-
self.unique_together = {tuple(cons) for cons in unique_together}
497+
def __init__(self, name, option_value):
498+
if option_value:
499+
option_value = set(normalize_together(option_value))
500+
setattr(self, self.option_name, option_value)
504501
super().__init__(name)
505502

503+
@cached_property
504+
def option_value(self):
505+
return getattr(self, self.option_name)
506+
506507
def deconstruct(self):
507508
kwargs = {
508509
'name': self.name,
509-
'unique_together': self.unique_together,
510+
self.option_name: self.option_value,
510511
}
511512
return (
512513
self.__class__.__qualname__,
@@ -516,14 +517,15 @@ def deconstruct(self):
516517

517518
def state_forwards(self, app_label, state):
518519
model_state = state.models[app_label, self.name_lower]
519-
model_state.options[self.option_name] = self.unique_together
520+
model_state.options[self.option_name] = self.option_value
520521
state.reload_model(app_label, self.name_lower, delay=True)
521522

522523
def database_forwards(self, app_label, schema_editor, from_state, to_state):
523524
new_model = to_state.apps.get_model(app_label, self.name)
524525
if self.allow_migrate_model(schema_editor.connection.alias, new_model):
525526
old_model = from_state.apps.get_model(app_label, self.name)
526-
schema_editor.alter_unique_together(
527+
alter_together = getattr(schema_editor, 'alter_%s' % self.option_name)
528+
alter_together(
527529
new_model,
528530
getattr(old_model._meta, self.option_name, set()),
529531
getattr(new_model._meta, self.option_name, set()),
@@ -536,67 +538,35 @@ def references_field(self, model_name, name, app_label=None):
536538
return (
537539
self.references_model(model_name, app_label) and
538540
(
539-
not self.unique_together or
540-
any((name in together) for together in self.unique_together)
541+
not self.option_value or
542+
any((name in fields) for fields in self.option_value)
541543
)
542544
)
543545

544546
def describe(self):
545-
return "Alter %s for %s (%s constraint(s))" % (self.option_name, self.name, len(self.unique_together or ''))
547+
return "Alter %s for %s (%s constraint(s))" % (self.option_name, self.name, len(self.option_value or ''))
548+
549+
550+
class AlterUniqueTogether(AlterTogetherOptionOperation):
551+
"""
552+
Change the value of unique_together to the target one.
553+
Input value of unique_together must be a set of tuples.
554+
"""
555+
option_name = 'unique_together'
556+
557+
def __init__(self, name, unique_together):
558+
super().__init__(name, unique_together)
546559

547560

548-
class AlterIndexTogether(FieldRelatedOptionOperation):
561+
class AlterIndexTogether(AlterTogetherOptionOperation):
549562
"""
550563
Change the value of index_together to the target one.
551564
Input value of index_together must be a set of tuples.
552565
"""
553566
option_name = "index_together"
554567

555568
def __init__(self, name, index_together):
556-
index_together = normalize_together(index_together)
557-
self.index_together = {tuple(cons) for cons in index_together}
558-
super().__init__(name)
559-
560-
def deconstruct(self):
561-
kwargs = {
562-
'name': self.name,
563-
'index_together': self.index_together,
564-
}
565-
return (
566-
self.__class__.__qualname__,
567-
[],
568-
kwargs
569-
)
570-
571-
def state_forwards(self, app_label, state):
572-
model_state = state.models[app_label, self.name_lower]
573-
model_state.options[self.option_name] = self.index_together
574-
state.reload_model(app_label, self.name_lower, delay=True)
575-
576-
def database_forwards(self, app_label, schema_editor, from_state, to_state):
577-
new_model = to_state.apps.get_model(app_label, self.name)
578-
if self.allow_migrate_model(schema_editor.connection.alias, new_model):
579-
old_model = from_state.apps.get_model(app_label, self.name)
580-
schema_editor.alter_index_together(
581-
new_model,
582-
getattr(old_model._meta, self.option_name, set()),
583-
getattr(new_model._meta, self.option_name, set()),
584-
)
585-
586-
def database_backwards(self, app_label, schema_editor, from_state, to_state):
587-
return self.database_forwards(app_label, schema_editor, from_state, to_state)
588-
589-
def references_field(self, model_name, name, app_label=None):
590-
return (
591-
self.references_model(model_name, app_label) and
592-
(
593-
not self.index_together or
594-
any((name in together) for together in self.index_together)
595-
)
596-
)
597-
598-
def describe(self):
599-
return "Alter %s for %s (%s constraint(s))" % (self.option_name, self.name, len(self.index_together or ''))
569+
super().__init__(name, index_together)
600570

601571

602572
class AlterOrderWithRespectTo(FieldRelatedOptionOperation):

0 commit comments

Comments
 (0)