<< ALL BLOG POSTS

A Look at Using Wagtail Snippets with Django

|
September 7, 2022
Table of Contents

Wagtail 4.0 came out on Aug. 31 and with it came support for Django 4.1, which we just so happen to be using for our first Wagtail project — a new application that will be integrated within one of the client’s existing websites.

The project revolves around the use of Snippets, Wagtail's model for creating bits of content/code that can be reused in other places in the site. In this case, we needed to use snippets to create a grid of content cards that could be edited by only certain users, but there are a number of other ways Snippets can be used, including:

  • repeating content blocks, like footer content or navigation that display on every page,
  • web advertisements; and
  • promotions that might redirect you to another part of the site.

The tricky part was setting the necessary permissions for different user groups, but we were able to do this using a migration file.

Using a migration to apply permissions

In version 4.0, Wagtail added the ability for Snippets to have drafts (previously they could only be in the published state). By default, only admins can add and publish snippets. But our project needed users other than admins to be able to add and publish snippets.

d7caolNQ.png

In addition to Django’s superusers, Wagtail has two user groups by default: editors and moderators. We wanted editors to be able to add and create draft snippets, but not publish. Then we needed moderators to be able to add, edit, and publish snippets.

Most of this can be done through Wagtail's groups settings, but we created migration steps to handle it. A migration can be used for applying settings that are different from default Django. This way it’s already set up with a new instance of the code so it doesn’t have to be set manually.

The one piece that couldn't be done through the web (other than creating the modal) was giving moderators permission to publish. But including it in the migration with the other permissions magically worked. You can see in the moderators group screenshot below how it appears under “Custom permissions.”

w7b2zbOQ.png

Here is the migration file we used to apply the permissions:

    from django.db import migrations
    
    def add_snippet_permissions_to_moderator_group(apps, schema_editor):
        ContentType = apps.get_model("contenttypes.ContentType")
        Permission = apps.get_model("auth.Permission")
        Group = apps.get_model("auth.Group")
        
        # Get snippet permissions
        card_content_type, _created = ContentType.objects.get_or_create(
            model="cardlayout", app_label="layouts"
        )
    
        add_card_permission, _created = Permission.objects.get_or_create(
            content_type=card_content_type,
            codename="add_cardlayout",
            defaults={"name": "Can add Card Layout"},
        )
        change_card_permission, _created = Permission.objects.get_or_create(
            content_type=card_content_type,
            codename="change_cardlayout",
            defaults={"name": "Can change Card Layout"},
        )
        view_card_permission, _created = Permission.objects.get_or_create(
            content_type=card_content_type,
            codename="view_cardlayout",
            defaults={"name": "Can view Card Layout"},
        )
        delete_card_permission, _created = Permission.objects.get_or_create(
            content_type=card_content_type,
            codename="delete_cardlayout",
            defaults={"name": "Can delete Card Layout"},
        )
        publish_card_permission, _created = Permission.objects.get_or_create(
            content_type=card_content_type,
            codename="publish_cardlayout",
            defaults={"name": "Can publish Card Layout"},
        )
    
        # Assign them to Moderators group
        for group in Group.objects.filter(name__in=["Moderators"]):
            group.permissions.add(
                add_card_permission,
                change_card_permission,
                view_card_permission,
                delete_card_permission,
                publish_card_permission,
            )
    
    class Migration(migrations.Migration):
        dependencies = [
            ("layouts", "0001_sample"),
        ]
        operations = [
            migrations.RunPython(add_snippet_permissions_to_moderator_group),
        ]

This saves you from having to manually apply these permissions when setting up a new instance of the site.

Read more Django best practices and Django case studies from Six Feet Up.

Related Posts
How can we assist you?
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.