-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Wagtail 4.1 and 4.2 support (revised) #52
Conversation
You can help test this PR by installing wagtail_ab_testing from my fork:
Disclaimer: I would strongly discourage using my fork on production. Don't add this to your requirements.txt. I may change or delete my fork at any time and am not responsible for broken sites. |
Got tox to run the test suite locally (CI for this project still depends on Travis CI, which has long gone) and all tests pass!
|
I just learned about the If I can get |
Thanks for working on this @Stormheg! Let me know if we can help. I'm eager to get this working for our projects :) |
Hi @harrislapiroff, thanks for your interest and sorry for my late reply! I have just added a commit that approaches the migration problem in a different way which I think is more elegant. All this needs is a review 🙌 |
I wonder if it can be dropped now, since Python 3.7 is EOL now. Though if it is complicated to remove, I think we can get this PR merged without the dropping change. I will review the PR as is for now. |
Hi @SaptakS, we can absolutely drop Python 3.7 but this PR already contains a lot of changes. I did not want to make this PR much larger |
Makes sense to me. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Stormheg as discussed over call, there's another usecase that I found where the project is already in Wagtail 4.2 and have all the migrations of 4.2 applied, but were not using Wagtail AB Testing package. So when they install the wagtail ab testing (based on this PR) and try to apply migrations, it fails because of the run_before
statements. This is because for such projects, the page revision migrations has already been applied and this is a fresh install.
I have tested with 3a557fb and the migrations work fine in the above case with the squashed migrations. I am testing the rest of the project to see if everything works as expected.
Thanks for testing this @SaptakS! I will make sure to drop the Let me know if you run into any issues. Otherwise, approve the PR and I'll get it merged and a new release out 🚀 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rest of the code looks good to me subject to run_before
commit is reverted and the squashed migrations are used.
and adjust the import paths to allow different wagtail versions
I removed the upper limits on wagtail and django versions.
Wagtail 4.0 changes this model name, so we need to update the migration to use the new name.
We cannot reference a model that does not exist yet in the migration history of existing databases. Migrating would fail with the following error: > ValueError: The field wagtail_ab_testing.AbTest.variant_revision was declared with a lazy reference to 'wagtailcore.revision', but app 'wagtailcore' doesn't provide model 'revision'.
Use AlterField instead of AddField because the `variant_revision` field is created already in migration history. Only changing the referenced model is necessary.
Migrating will fail for fresh databases because the PageRevision model does not exist. Squashing all migrations fixes this because we never reference PageRevision this way, only Revision. See comment in source code for a detailed explanation.
The older version that were specified fail to install on my machine - probably on other machines too.
The initial migration must continue to rely on the historical PageRevision model. Changing it to the generic revision model may cause errors with existing databases that have migrations applied in a certain order. New databases won't be able to migrate because they have no history and try to migrate the initial migration using the PageRevision model _after_ it was removed by Wagtail's migrations. To combat this, we add `run_before` to ensure we run the initial migration _before_ the PageRevision model is removed by Wagtail's migrations. I feel like this is a better solution then squashing the migration history.
This reverts commit 4e0e127. The run_before approach does not work properly if ab_testing is installed in a project that is already on Wagtail 4 and has the PageRevision to Revision migration applied. In this case, is not possible to make our initial migration run before Wagtail's migration. Thanks to Saptak Sengupta for pointing this out.
27eb9bb
to
8211e64
Compare
Anyone hits this in the future, you need to both change your target model back to to='wagtailcore.pagerevision') and run_before = [
("wagtailcore", "0067_alter_pagerevision_content_json"),
] |
This PR supersedes #51, #49 and #48
I took all changes from @nickmoreton's fork and applied a fix to the PageRevision to Revision migration + some formatting fixes. I don't have push access to their fork, hence this new PR. All open comments from #51 should have been addressed in this PR.
I've decided to not drop Python 3.7 support in this PR (I requested this in #51). I'm planning on fixing the CI and will drop support for 3.7 as part of that future PR, just want to get this merged in.
PageRevision to Revision migration
Migrations like this are tricky to do correctly.
I've investigated the best solution for this that works for both existing and fresh databases.
If we look at how
PageRevision
was changed toRevision
in Wagtail 4 (link to migration), we can seePageRevision
was renamedRevision
using Django'sRenameModel
migration operation. As a side-effect of this, all foreign keys referencing this model will be updated as well. This includes the ForeignKey towagtailcore.pagerevision
.With above knowledge in mind, I've been experimenting with how Django handles renaming a model and what happens when migrating existing databases and 'new' databases.
I've discovered that this is very tricky to get right because of the order in which migrations are applied.
If we:
Revision
model instead ofPageRevision
dependencies
list to make sure the initial migration is applied after Wagtail has migrated to theRevision
model (like done now; except for the change todependencies
)The result would be that this would work for new databases but not existing databases because changing the dependencies list will result in inconsistent migration history. If we don't alter the dependencies, we risk our migration being applied before Wagtail's, which would result in an error either way.
If we don't alter the initial migration and only generate an
AlterField
migration to change the foreign key the result would be that this would work for existing databases but not for new databases. Again, all of this is caused by the order in which migrations are applied.Summary
We need to change the dependencies of our initial migration to be able to apply it on a fresh database but by doing so we create inconsistent migration history for existing databases.
Solution implemented in this PR
I found the best way to solve this is to leave the initial migration untouched and generate a new migration with an
AlterField
operation to change the foreign key. This works for existing databases.To support new installations, I squashed the entire migration history and use Wagtail's Revision model from the start. This avoids the
ValueError: Related model 'wagtailcore.pagerevision' cannot be resolved
error when migrating the0001_initial
migration, which must continue to reference the old PageRevision model because we cannot alter its dependencies.Testing process I followed
I tested the migration from Wagtail 2.16 to Wagtail 4.2 by checking out the bakerydemo project @ commit 75eab056f09aef5b3440b1d1ea4c04cfb40414e0, installing wagtail_ab_testing from
main
and created an AB test for the about page.Next, I checked out bakerydemo @ commit 8cb4c0a60e12ed0e258a62e6ccc3bcfa46b290e3 and installed wagtail_ab_testing from this branch. I kept the database intact to see if the migration to the Revision model works properly for databases with existing data and history. I'm glad to report this migrates successfully for me with no errors!
I then deleted the database and ran all bakerydemo from scratch to simulate a fresh database. This fresh database only applies the
0001_squashed_0012_abtest_variant_revision
migration like expected, with no errors.