Add proper support for pre/post migrate/sync signals.
Review Request #10582 — Created June 7, 2019 and submitted
We were trying to emit
pre_migrate/post_migratesignals in
apply_migrations(), which was always intended to be temporary. While
emitting them there sort of worked at one point (when there was only one
migration phase), it falls apart pretty hard with some apps with
multiple migration phases. The reason is that some apps will use the
post_migratesignal to inject some state into the database for the new
models, but this happens too soon when emitted during the initial
migration phase.We also weren't emitting the
pre_syncandpost_syncsignals on
Django 1.6 and earlier (1.7 and 1.8 would emit them for
backwards-compatibility, though).To solve all this, this change does four things:
It switches to emitting the
pre_migratesignal only once, before
any migrations are applied, andpost_migrateonly once, after all
migrations are applied.It introduces a full migration plan that encompasses all phases of
the migrations, which allows us to provide some useful state in these
signals. This is important as some apps listen topre_migrateand
then modify the migration instances that are to be later applied.It also splits
apply_migrations()into three functions:
create_pre_migrate_state(),apply_migrations(), and
finalize_migrations(). This allows repeated alterations of the same
migration state, and a single final model rendering phase, better
mirroring what's done directly in Django'smigratecommand.It emits
pre_syncandpost_syncsignals on Django 1.6 and
earlier.
Unit tests pass on all supported versions of Django.
Manually tested population of a new database and upgrades of an
existing one (utilizing both migrations and evolutions).
| Summary | ID |
|---|---|
| 04e561d54c8686fe89a8c40c8e6b28195f06fea0 |
- Change Summary:
-
Updated to support
pre_syncandpost_syncsignals. - Summary:
-
Add proper support for pre_migrate/post_migrate signals.Add proper support for pre/post migrate/sync signals.
- Description:
-
We were trying to emit
pre_migrate/post_migratesignals inapply_migrations(), which was always intended to be temporary. Whileemitting them there sort of worked at one point (when there was only one migration phase), it falls apart pretty hard with some apps with multiple migration phases. The reason is that some apps will use the post_migratesignal to inject some state into the database for the newmodels, but this happens too soon when emitted during the initial migration phase. ~ To solve this, this change does three things:
~ We also weren't emitting the
pre_syncandpost_syncsignals on+ Django 1.6 and earlier (1.7 and 1.8 would emit them for + backwards-compatibility, though). + + To solve all this, this change does four things:
-
It switches to emitting the
pre_migratesignal only once, before
any migrations are applied, andpost_migrateonly once, after all
migrations are applied.
-
It introduces a full migration plan that encompasses all phases of
the migrations, which allows us to provide some useful state in these
signals. This is important as some apps listen topre_migrateand
then modify the migration instances that are to be later applied.
-
It also splits
apply_migrations()into three functions:
create_pre_migrate_state(),apply_migrations(), and
finalize_migrations(). This allows repeated alterations of the same
migration state, and a single final model rendering phase, better
mirroring what's done directly in Django'smigratecommand.
+ -
It emits
pre_syncandpost_syncsignals on Django 1.6 and
earlier.
-
- Commits:
-
Summary ID 6b3ad131b17c5c92baf0d516809f171ddb0eef22 04e561d54c8686fe89a8c40c8e6b28195f06fea0