Bud
Bud

Reputation: 1491

Wagtail: get parent page groups that have specific rights (edit, delete)

I have a categorypage -> articlepage hierarchy in wagtail. The article page has an author field, which currently shows all users in the system. I want to filter the authors of the article based on the group of the parent category page.

models.py

from django.contrib.auth.models import Group

class CategoryPage(Page):  # query service, api
    blurb = models.CharField(max_length=300, blank=False)
    content_panels = Page.content_panels + [
        FieldPanel('blurb', classname="full")
    ]
    subpage_types = ['cms.ArticlePage']


class ArticlePage(Page):  # how to do X with query service
    ...
    author = models.ForeignKey(User, on_delete=models.PROTECT, default=1,
                           # limit_choices_to=get_article_editors,
                           help_text="The page author (you may plan to hand off this page for someone else to write).")

def get_article_editors():
    # get article category
    # get group for category
    g = Group.objects.get(name='??')
    return {'groups__in': [g, ]}

This question (limit_choices_to) is almost what I'm after, but I'm not sure how to retrieve the group for the parent page before the article itself is created?

This question seems to do the trick in accessing parent pages on creation, but I remain unsure of how to find the groups that can edit the parent page.

Upvotes: 0

Views: 805

Answers (1)

Loïc Teixeira
Loïc Teixeira

Reputation: 1434

Unfortunately I am not aware of a way for the limit_choices_to function to receive a reference to the parent objects. Your second link is on the right track, we will need to provide our own base form to the page and tweak the queryset of the author field.

from django.contrib.auth.models import Group
from wagtail.wagtailadmin.forms import WagtailAdminPageForm
from wagtail.wagtailcore.models import Page


class ArticlePageForm(WagtailAdminPageForm):
    def __init__(self, data=None, files=None, parent_page=None, *args, **kwargs):
        super().__init__(data, files, parent_page, *args, **kwargs)

        # Get the parent category page if `instance` is present, fallback to `parent_page` otherwise.
        # We're trying to get the parent category page from the `instance` first
        # because `parent_page` is only set when the page is new (haven't been saved before).
        instance = kwargs.get('instance')
        category_page = instance.get_parent() if instance and instance.pk else parent_page
        if not category_page:
            return  # Do not continue if we failed to find the parent category page.

        # Get the groups which have permissions on the parent category page.
        groups = Group.objects.filter(page_permissions__page_id=category_page.pk).distinct()
        if not groups:
            return  # Do not continue if we failed to find any groups.

        # Filter the queryset of the `author` field.
        self.fields['author'].queryset = self.fields['author'].queryset.filter(groups__in=groups)


class ArticlePage(Page):
    base_form_class = ArticlePageForm

A quick note on the way we query the groups: When you set page permissions in Wagtail, you actually create a GroupPagePermission which has 2 main attributes, group and page. The related_name of the group's foreign key of the GroupPagePermission is defined as page_permissions and every time you create a ForeignKey like with page, it actually creates a field called page_id. Therefore we can follow the relationship and filter the groups by page_permissions__page_id with the ID of the parent category page.

Upvotes: 3

Related Questions