django
django copied to clipboard
Fixed #24529 - Allow double squashing of migrations
In order to support multi-level squashing, we need to be a bit smarter about how we traverse replacements. The solution here introduces some extra checks on squashed migrations (mainly a lookup for whether its replacements need to be squashed first), but the performance hit shouldn't be very large.
This is missing documentation updates and changelog entries, but I would like to get a first look at the implementation strategy here, as well as field any extra testing requests before going further down this path.
@rtpg Do you have time to keep working on this?
Hey @felixxm, thanks for the ping, this one fell by the wayside. Will find some time to work on this (unless someone else wants to pick it up and run with it, of course. I just want the feature in place)
Alright I spent some time looking at this (mainly identifying that the existing test does indeed fail with the old code sometimes), would just like some confirmation about whether my game plan (to add one test for the cycle detection code, clean up the lint issues) sounds like a good game plan here.
I also am a bit unsatisfied with various little lines of code here, though it's not so much correctness as it is legibility. Searching for strings in the generated migrations feels weird to be honest. Also a bit lost as to how to make that memoization code very clean...
In short, a bit of guidance would be appreciated
Added the missing test and tried to clean up the code to the best of my abilities. Will look at changelog/doc editing tomorrow, a cursory search didn't mead me to any obvious documentation changes, but I know there has to be something.
I believe to have answered all the outstanding questions on this branch, so it should be ready for a re-review!
@rtpg Thanks for this patch :+1: I have an issue in the following scenario:
- app with 3 migrations:
-
0001_initial.py
-
0002_mymodel1_field_1_mymodel2_field_2_and_more.py
, -
0003_alter_mymodel2_unique_together.py
,
-
- steps:
- apply migrations
0001
and0002
:python manage.py migrate test_one 0002
- squash migrations
0001
→0003
:python manage.py squashmigrations test_one 0001 0003
- make a change in the models definition and create a new migration file
0004_remove_mymodel1_field_1_mymodel1_field_3_and_more.py
:python manage.py makemigrations
, - squash migrations
0001
→0004
:python manage.py squashmigrations test_one 0001_initial_squashed 0004
Traceback (most recent call last): File "manage.py", line 22, in <module> main() File "manage.py", line 18, in main execute_from_command_line(sys.argv) File "/django/django/core/management/__init__.py", line 446, in execute_from_command_line utility.execute() File "/django/django/core/management/__init__.py", line 440, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/django/django/core/management/base.py", line 402, in run_from_argv self.execute(*args, **cmd_options) File "/django/django/core/management/base.py", line 448, in execute output = self.handle(*args, **options) File "/django/django/core/management/commands/squashmigrations.py", line 100, in handle start = loader.get_migration( File "/django/django/db/migrations/loader.py", line 144, in get_migration return self.graph.nodes[app_label, name_prefix] KeyError: ('test_one', '0001_initial_squashed_0003_alter_mymodel2_unique_together')
- apply migrations
Sample project: ticket_24529.zip.
Closing due to inactivity.