New Wagtail Course! 🥳 The Ultimate Wagtail Developers Course

Upgrading From Wagtail 4.0 to Wagtail 5.0

Upgrading to Wagtail 5.0 from Wagtail 4.0

Categories

### Transitioning to Wagtail 5.0 and Beyond The release of Wagtail 5.0 brings a host of changes, primarily focusing on removing deprecated features and cleaning up the codebase to pave the way for more streamlined future updates. As you prepare to upgrade, it’s crucial to review the [upgrade considerations](https://docs.wagtail.org/en/stable/releases/5.0.html#upgrade-considerations) to ensure compatibility and smooth transition. ### Understanding the Changes Wagtail 5.0 has taken significant strides in removing old features that were deprecated in previous versions. To grasp the extent of these changes, check the detailed list of removed features on the [official documentation](https://docs.wagtail.org/en/stable/releases/5.0.html#removal-of-deprecated-features). ### Preparing for Upgrade Looking ahead, Wagtail 5.0 supports Django 4.2, which is a key piece of information for managing dependencies. However, starting from Wagtail 5.1, support for Python 3.7 will be dropped, necessitating an upgrade to at least Python 3.8 or higher to maintain support. Here’s how to start updating your environment: #### Update Your `requirements.txt` Adjust your project dependencies to align with the new version requirements: ``` Django==4.2.11 wagtail==5.0 ``` For a fun tip on finding Django versions, try running a nonsensical install command like `pip install Django==123123123123123` in your terminal. This will trigger an error that lists all available versions! #### Removing Deprecated Packages If you’re using the `pytz` package, consider removing it. Django has deprecated `pytz` as of Django 4.0, and it will be completely removed in Django 5.0. 🫠 ### Handling Major Import Changes One of the crucial updates in Wagtail 5.0 is the change in settings models: ```python # Old import from wagtail.contrib.settings.models.BaseSetting # New import from wagtail.contrib.settings.models.BaseSiteSetting ``` ### Running Migrations and Server After updating your settings and requirements, apply the database migrations and test the server: ``` python manage.py migrate python manage.py runserver 0.0.0.0:8000 ``` This will help confirm that all changes are functioning as expected. ### Python and Django Upgrades Given the forthcoming end of support for older Python versions, upgrading to Python 3.10 is advisable to fully benefit from future Django releases. If you're using Docker that's as simple as: 👇 ```Dockerfile FROM python:3.7 ``` To: 👇 ```Dockerfile FROM python:3.10 ``` **If upgrading Python isn’t an option, stick with Wagtail 5.2.4 and let Django default to version 4.2.11 to maintain compatibility.** ### Upgrading to Wagtail 5.2 LTS Next, the step towards Wagtail 5.2 LTS involves further refinements and stability improvements: ``` # requirements.txt for Wagtail 5.2 LTS wagtail==5.2.4 Django==5.0 ``` Review the [Wagtail 5.2 LTS release notes](https://docs.wagtail.org/en/stable/releases/5.2.html) to fully understand the enhancements and any additional changes. ### Handling Docker and Django 5.0 Compatibility If you’re leveraging Docker for your Wagtail project, remember to rebuild your Docker image with the new `requirements.txt` to ensure all dependencies are correctly updated. Note that Wagtail 5.2.2 added support for Django 5.0, but you will need to upgrade beyond Wagtail 5.2 LTS to utilize Django 5.0. You might choose to wait until the upgrade to Wagtail 6.0 if you prefer to jump directly to newer versions. ### Managing Migrations and Warnings Upon running migrations and your server, you’ll likely encounter several warnings alongside the necessity to apply migrations: ``` python manage.py migrate python manage.py runserver 0.0.0.0:8000 ``` Typical warnings you might see include: ``` /python3.10/site-packages/wagtail/search/index.py:301: RemovedInWagtail60Warning: The partial_match option on SearchField has no effect and will be removed. Use AutocompleteField instead. /python3.10/site-packages/wagtail/contrib/modeladmin/apps.py:15: RemovedInWagtail60Warning: wagtail.contrib.modeladmin is deprecated. Use wagtail.snippets or the separate wagtail-modeladmin package instead. ``` These warnings alert you to the removal of certain features or recommend better alternatives: - **SearchField’s partial_match is deprecated**: Replace it with `AutocompleteField` to maintain functionality. - **wagtail.contrib.modeladmin is deprecated**: Transition to using `wagtail.snippets` or the standalone `wagtail-modeladmin` package. ### Resolving Deprecated Features To address the `partial_match` deprecation in your search fields: ```python class YourPage(Page): ... search_fields = Page.search_fields + [ index.SearchField('title', partial_match=True, boost=10), # Old index.AutocompleteField('title', partial_match=True, boost=10), # New ] ``` For transitioning away from `modeladmin`, consider using `ModelViewSets`, which provide a more robust and flexible system for managing models within the Wagtail admin. ### Transitioning to ModelViewSets The shift from `ModelAdmin` to `ModelViewSets` is part of Wagtail's efforts to enhance and streamline admin capabilities. An old (pre-Wagtail 5.0) ModelAdmin class would look like this inside of the `wagtail_hooks.py` file: ``` from wagtail.contrib.modeladmin.options import ModelAdmin, from .models import MyCustomModel @modeladmin_register class MyCustomModelAdmin(ModelAdmin): model = MyCustomModel menu_label = "Custom Model Label" menu_icon = "pilcrow" menu_order = 200 add_to_settings_menu = False exclude_from_explorer = False list_display = ("name", "description", "category") # These are model FieldNames list_filter = ("category",) search_fields = ("name",) ``` ☝️ That is the old way. Below is the new way to manage models via the Wagtail admin:. 👇 ```python # views.py from wagtail.admin.viewsets.model import ModelViewSet from .models import MyCustomModel class MyCustomModelModelViewSet(ModelViewSet): model = MyCustomModel icon = "pilcrow" list_display = ("name", "description", "category") list_filter = ("category",) search_fields = ("name",) menu_label = "Custom Model Label (New)" add_to_admin_menu = True exclude_form_fields = [] my_model_viewset = MyCustomModelModelViewSet("my_model") # URL base /admin/my_model/ ``` Register this viewset in `wagtail_hooks.py`: ```python # wagtail_hooks.py from wagtail import hooks from .views import my_model_viewset @hooks.register("register_admin_viewset") def register_viewset(): return my_model_viewset ``` This setup simplifies admin interfaces and consolidates management under Wagtail, reducing confusion among users with multiple admin panels. ### Django Auth Changes If you're using `django.contrib.auth` for authentication on your Wagtail/Django website, you may need to look at the `{% url 'logout' %}` URL. Prior to Django 4.1, you can use a standard GET (HTML link) to log out. But moving forward, you'll want to consider using a POST request. The quickest way to implement this is: ```html <form method="post" action="{% url 'logout' %}" id="logout-form"> {% csrf_token %} </form> <a href="#" onclick="document.getElementById('logout-form').submit();"> Logout </a> ``` ### Final Steps Before Wagtail 6.0 With these updates and transitions in place, your Wagtail installation is not only cleaner but also prepared for the upcoming migration to Wagtail 6.0. These changes ensure that your platform utilizes the latest and most efficient practices, keeping your site secure and performant.

Kalob Taulien

Wagtail CMS enthusiast; Wagtail core team member; Coding teacher.

Get notified about new Wagtail content.