Skip to content

Wagtail

Michael Beaton edited this page Nov 25, 2022 · 2 revisions

Wagtail pages can be mentionable too!

Remember to add your endpoint link to your templates!

You can make your Wagtail Page models mentionable by implementing MentionableMixin as follows:

from wagtail.contrib.routable_page.models import RoutablePageMixin, path  
from wagtail.fields import RichTextField  
from wagtail.models import Page  
from wagtail.templatetags.wagtailcore_tags import richtext

class MentionablePage(MentionableMixin, Page):  
    body = RichTextField(blank=True)  
    date = models.DateField(default=timezone.now)  
  
    def get_absolute_url(self):  
        return self.get_url()  
  
    def get_content_html(self) -> str:  
        return richtext(self.body)

    def should_process_webmentions(self) -> bool:  
        """Return True if this instance should process webmentions when saved."""  
        return self.live

We need to add some extra information in order to make your MentionableMixin Pages resolve correctly when using routable views. Replace your @path or @re_path decorators with one of the following.

Both of these accept the same parameters as the decorators that they replace, but also add a few of their own.

@mentions_wagtail_path

Extra parameters:

  • model_class (required): The class that this view queries.
  • model_filter_map: If captured parameters from your URL pattern do not correspond to model fields of the same name, provide a dict of captured_url_param: model_filter. This can be omitted if the names are equal.

Examples

Captured params same as model field names

model_filter_map can be omitted because the names in the URL are the same as the fields they correspond to.

from mentions.helpers.thirdparty.wagtail import mentions_wagtail_path

@mentions_wagtail_path(  
    "<int:pk>/",  
    MentionablePage,  
)  
def post_by_pk(self, request, pk):  
    page = MentionablePage.objects.get(pk=pk)  
    return page.serve(request)
Mapping captured params to model filters

model_filter_map is required to associate captured names with a model filter.

from mentions.helpers.thirdparty.wagtail import mentions_wagtail_path

@mentions_wagtail_path(  
    "<int:year>/<int:month>/<int:day>/",  
    model_class=MentionablePage,  
    model_filter_map={  
        "year": "date__year",  
        "month": "date__month",  
        "day": "date__day",  
    },  
)  
def post_by_date(self, request, year, month, day):  
    page = MentionablePage.objects.get(  
        date__year=year,  
        date__month=month,  
        date__day=day,  
    )
    return page.serve(request)

@mentions_wagtail_re_path

Extra parameters:

  • model_class (required): The class that this view queries.
  • model_filter_map: If captured parameters from your URL pattern do not correspond to model fields of the same name, provide a dict of captured_url_param: model_filter. This can be omitted if the names are equal.
  • model_filters : If your regex does not name its captured groups, provide a list of model_filter values that the groups represent.

Examples

Named regex groups

model_filter_map is required to associate captured names with a model filter.

from mentions.helpers.thirdparty.wagtail import mentions_wagtail_re_path

@mentions_wagtail_re_path(  
    r"^(?P<year>\d{4})/(?P<month>\d{2})/(?P<slug>.+)/$",  
    model_class=MentionablePage,  
    model_filter_map={  
        "year": "date__year",  
        "month": "date__month",  
        "slug": "slug",  
    },  
)  
def post_by_date_slug_regex_with_named_groups(self, request, year, month, slug):  
    page = MentionablePage.objects.get(  
        date__year=year,  
        date__month=month,  
        slug=slug,  
    )
    return page.serve(request)
Unnamed regex groups

model_filters is required so that each captured group can be associated with a model filter.

from mentions.helpers.thirdparty.wagtail import mentions_wagtail_re_path

@mentions_wagtail_re_path(  
    r"^(\d{4})/(\d{2})/(.+)/$",  
    model_class=MentionablePage,  
    model_filters=("date__year", "date__month", "slug"),  
)  
def post_by_date_slug_regex_with_unnamed_groups(self, request, year, month, slug):  
    page = MentionablePage.objects.get(  
        date__year=year,  
        date__month=month,  
        slug=slug,  
    )
    return page.serve(request)

A little bit of magic

You may notice that the examples above each define the same query twice, albeit in slightly different formats. If that bothers you, try adding autopage=True to your decorator like so:

@mentions_wagtail_path(  
    "<int:year>/<int:month>/<int:day>/",  
    model_class=MentionablePage,  
    model_filter_map={  
        "year": "date__year",  
        "month": "date__month",  
        "day": "date__day",  
    },  
    autopage=True,
)  
def post_by_date(self, request, page):  
    return page.serve(request)

The decorator will resolve the page using the given filters and pass it to your view function. This works with mentions_wagtail_re_path too, using named or unnamed groups.

This won't be suitable for every usecase but if your views are as simple as these examples then it can help to keep things tidy.