Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to filter page lists in the wagtail admin so editors only see pages they created?

Tags:

wagtail

I'm creating a wagtail site where users may signup, login to the wagtail admin and write article pages to publish. Is there a hook or possible way to intercept and filter data in the wagtail admin so that users see only the article pages they themselves created?

So far I've set up user registration with django-allauth and users are able to successfully login. Once registered the user_signed_up receiver fires and the user is assigned to the 'Author' role. In the admin, author's only have access to add articles. Articles is an app with an article index page and article page (basically a blog and blog index page). Once they login the only thing they see is the Pages tab on the left, clicking on that takes them to the 'Articles' list. This is where they are able to add an 'Article' page and view their articles created so far.

It's also where my problem is. From the Articles list page, the users are able to see all the articles created by all users on the site. They are only able to edit their own which is great, but eventually there will be hundreds of articles from others users. Is there a way to intercept the 'Articles' data before its displayed and filter it by the current user?

The result of intercepting this data would then keep each user that is logged in to the wagtail admin aware of only the article pages that they have created.

Much thanks, it's my first time using Wagtail and I'm enjoying it so far.

like image 433
Mike Avatar asked Oct 20 '25 09:10

Mike


1 Answers

I discovered two different solutions to this question.

  1. Implement ModelAdmin to create a custom page list view of your model. This lets you create an entirely new admin menu item and corresponding list view. This method is more involved but offers more control.
  2. Implement the construct_explorer_page_queryset admin hook to filer results by group. This method is quick and easy to implement and allows you to use Wagtails existing page explorer.

I'll go over how I handled each of the above methods. Both worked, it's a matter of deciding whether I prefer to use Wagtails built in page explorer or not.

Method 1: ModelAdmin

The use of ModelAdmin.get_queryset() and other helpful methods were found in the Wagtail Docs here.

As per this page in the Wagtail docs I added ModelAdmin to INSTALLED_APPS:

# base.py settings

INSTALLED_APPS = [
    ...
    'wagtail.contrib.modeladmin',
]

Then I created a file named wagtail_hooks.py in my 'article' app. In that file I added the code to create my article listing page in the admin:

# wagtail_hooks.py

from wagtail.contrib.modeladmin.options import (ModelAdmin, modeladmin_register)
from .models import Article


class ArticleAdmin(ModelAdmin):
    model = Article
    menu_label = 'Articles'
    menu_icon = 'doc-full-inverse'
    menu_order = 000
    add_to_settings_menu = False
    exclude_from_explorer = False
    list_display = ('title', 'owner')
    search_fields = ('title', 'owner')

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        #only show articles from the current user
        return qs.filter(owner=request.user)


modeladmin_register(ArticleAdmin)

They key here was to implement ModelAdmin.get_queryset() which let me filter the articles owner.

You'll also likely want to remove the Page explorer menu item as it's a bit redundant. I also recommend implementing Method 2 below as well. Even if you remove the Page explorer menu item the user could possibly get there by entering the URL directly in the browser. If they do, implementing Method 2 will ensure the do not see content authored by other users.

Method 2: construct_explorer_page_queryset @hooks

The hook information in Wagtail's documentation - construct_explorer_page_queryset Also referenced this Google Groups article - https://groups.google.com/forum/#!topic/wagtail/10tcq8PB8io

In the same wagtail_hooks.py file I created above I added this code:

@hooks.register('construct_explorer_page_queryset')
def show_authors_only_their_articles(parent_page, pages, request):
    user_group = request.user.groups.filter(name='Author').exists()
    if user_group:
        pages = pages.filter(owner=request.user)

    return pages

That's it for the second method.

like image 62
Mike Avatar answered Oct 22 '25 05:10

Mike



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!