Upgrading to Wagtail CMS 2.0 (and Django 2.0)

March 14, 2018

Just last week I upgraded this site from Wagtail 1.1 to Wagtail 1.13.1, then on Friday Wagtail 2.0 was released! Another upgrade to do! Many thanks to the fine Wagtail team for producing such a lovely CMS.

Wagtail 2.0 is quite a big release with some significant breaking changes. There are some upgrade considerations in the release notes that go some way to assisting with the process, but there were still a few other things I had to do, mostly to do with the antiquity of this site.

Basic upgrades

Firstly I updated my requirements.txt file to include Wagtail 2.0 and Django 2.0, then did a pip install -r requirements.txt. This replaced Django and Wagtail with their shiny new versions, as well as all the supporting modules.

One of the bigger changes in Wagtail 2.0 was the module path updates for all the internal modules. This makes for much neater imports statements and module references, but it does mean all these references need to be updated. Fortunately, a script is included to automatically update these references, like so: wagtail updatemodulepaths --list.

Unexpected issues

With that done, I found a few more issues when attempting to start my development copy. I was getting ImportError: cannot import name 'RegexURLPattern'. It turns out I had an older version of rest_framework in my python virtual environment site modules. I simply re-created my virtual env and the error went away.

After fixing this I could try to run any missing migrations. Unforutnatley the initial migrations I had for my site were no longer compatible with the new model api. I had to add on_delete=django.db.models.deletion.CASCADE to my initial migrations. I don't think adding this should cause any issues since it was the default behaviour for the one-to-one fields it was on.

With the migrations now run, I could try doing a http request to the server! Unfortunately I was getting this error: AttributeError: 'WSGIRequest' object has no attribute 'site'. This problem was because of how middleware classes are defined in Django 2.0. Previously MIDDLEWARE_CLASSES was set in my settings file, but with Django 1.10 this was changed to just MIDDLEWARE. As long as your middleware classes are compatible with the new api this should be an easy change (It was for me anyway). I also had to remove 'django.middleware.security.SecurityMiddleware', since it seems this is no longer shipped with Django.

Finally, the site was working locally!

Deploying to Production

With the main issues now resolved, I could deploy to production. After a quick collectstatic command everything seemed to be operating normally, but when I tried to edit a page I would get a CSRF error. Django now requires you to tell it which referrer origins are trusted for your site, to prevent CSRF attacks. This is simply defined like so in your settings module:

CSRF_TRUSTED_ORIGINS = [ 'graniteoctopus.com' ]

Now everything seems to be working, running on the lovely Wagtail 2.0 and Django 2.0. Woo!

All posts