1
0
mirror of https://github.com/django/django.git synced 2025-10-31 09:41:08 +00:00

Fixed #34856 -- Fixed references to index_together in historical migrations.

While AlterUniqueTogether has been documented to be still allowed in historical
migrations for the foreseeable future it has been crashing since 2abf417c81
was merged because the latter removed support for Meta.index_together which the
migration framework uses to render models to perform schema changes.

CreateModel(options["unique_together"]) was also affected.

Refs #27236.

Co-authored-by: Simon Charette <charette.s@gmail.com>
This commit is contained in:
Andrés Reverón Molina
2024-12-16 13:54:51 +01:00
committed by Sarah Boyce
parent 44281bc212
commit b44efdfe54
4 changed files with 234 additions and 11 deletions

View File

@@ -95,6 +95,17 @@ class CreateModel(ModelOperation):
model = to_state.apps.get_model(app_label, self.name)
if self.allow_migrate_model(schema_editor.connection.alias, model):
schema_editor.create_model(model)
# While the `index_together` option has been deprecated some
# historical migrations might still have references to them.
# This can be moved to the schema editor once it's adapted to
# from model states instead of rendered models (#29898).
to_model_state = to_state.models[app_label, self.name_lower]
if index_together := to_model_state.options.get("index_together"):
schema_editor.alter_index_together(
model,
set(),
index_together,
)
def database_backwards(self, app_label, schema_editor, from_state, to_state):
model = from_state.apps.get_model(app_label, self.name)
@@ -700,12 +711,13 @@ class AlterTogetherOptionOperation(ModelOptionOperation):
def database_forwards(self, app_label, schema_editor, from_state, to_state):
new_model = to_state.apps.get_model(app_label, self.name)
if self.allow_migrate_model(schema_editor.connection.alias, new_model):
old_model = from_state.apps.get_model(app_label, self.name)
from_model_state = from_state.models[app_label, self.name_lower]
to_model_state = to_state.models[app_label, self.name_lower]
alter_together = getattr(schema_editor, "alter_%s" % self.option_name)
alter_together(
new_model,
getattr(old_model._meta, self.option_name, set()),
getattr(new_model._meta, self.option_name, set()),
from_model_state.options.get(self.option_name) or set(),
to_model_state.options.get(self.option_name) or set(),
)
def database_backwards(self, app_label, schema_editor, from_state, to_state):

View File

@@ -323,13 +323,14 @@ class ProjectState:
for from_field_name in from_fields
]
)
# Fix unique_together to refer to the new field.
# Fix index/unique_together to refer to the new field.
options = model_state.options
if "unique_together" in options:
options["unique_together"] = [
[new_name if n == old_name else n for n in together]
for together in options["unique_together"]
]
for option in ("index_together", "unique_together"):
if option in options:
options[option] = [
[new_name if n == old_name else n for n in together]
for together in options[option]
]
# Fix to_fields to refer to the new field.
delay = True
references = get_references(self, model_key, (old_name, found))
@@ -947,7 +948,11 @@ class ModelState:
def render(self, apps):
"""Create a Model object from our current state into the given apps."""
# First, make a Meta object
meta_contents = {"app_label": self.app_label, "apps": apps, **self.options}
meta_options = {**self.options}
# Prune index_together from options as it's no longer an allowed meta
# attribute.
meta_options.pop("index_together", None)
meta_contents = {"app_label": self.app_label, "apps": apps, **meta_options}
meta = type("Meta", (), meta_contents)
# Then, work out our bases
try: