Как фильтровать списки страниц в wagtail admin, чтобы редакторы видели только созданные ими страницы?

#wagtail

#wagtail

Вопрос:

Я создаю сайт wagtail, где пользователи могут зарегистрироваться, войти в wagtail admin и написать страницы статей для публикации. Есть ли перехват или возможный способ перехватывать и фильтровать данные в wagtail admin, чтобы пользователи видели только страницы статей, которые они сами создали?

На данный момент я настроил регистрацию пользователей в django-allauth, и пользователи могут успешно входить в систему. После регистрации срабатывает приемник user_signed_up, и пользователю назначается роль «Автор». В admin у авторов есть доступ только к добавлению статей. Статьи — это приложение со страницей индекса статьи и страницей статьи (в основном, блог и страница индекса блога). После входа в систему единственное, что они видят, это вкладку «Страницы» слева, щелчок по которой приводит их к списку «Статьи». Здесь они могут добавить страницу «Статья» и просмотреть свои статьи, созданные на данный момент.

В этом также заключается моя проблема. На странице списка статей пользователи могут видеть все статьи, созданные всеми пользователями на сайте. Они могут редактировать только свои собственные, что здорово, но в конечном итоге появятся сотни статей от других пользователей. Есть ли способ перехватить данные «Статей» до их отображения и отфильтровать их по текущему пользователю?

В результате перехвата этих данных каждый пользователь, вошедший в wagtail admin, будет знать только о созданных им страницах статей.

Большое спасибо, я впервые использую Wagtail, и пока мне это нравится.

Комментарии:

1. Я наткнулся на ModelAdmin в документах Wagtail, и это вполне может быть то, что я ищу: Документы Wagtail — ModelAdmin

Ответ №1:

Я обнаружил два разных решения этого вопроса.

  1. Внедрите ModelAdmin для создания пользовательского представления списка страниц вашей модели. Это позволяет вам создать совершенно новый пункт меню администратора и соответствующий вид списка. Этот метод более сложный, но предлагает больше контроля.
  2. Внедрите хук администратора construct_explorer_page_queryset для сортировки результатов по группам. Этот метод быстр и прост в реализации и позволяет использовать Wagtails существующий проводник страниц.

Я расскажу, как я обрабатывал каждый из вышеперечисленных методов. Оба варианта сработали, нужно решить, предпочитаю ли я использовать Wagtails, встроенные в page Explorer, или нет.

Способ 1: ModelAdmin

Использование ModelAdmin.get_queryset() и других полезных методов было найдено в документах Wagtail здесь.

Согласно этой странице в документах Wagtail, я добавил ModelAdmin в INSTALLED_APPS:

 # base.py settings

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

Затем я создал файл с именем wagtail_hooks.py в моем приложении «статьи». В этот файл я добавил код для создания страницы со списком статей в 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)
  

Ключевым моментом здесь была реализация ModelAdmin.get_queryset(), которая позволяла мне фильтровать владельца статей.

Вы также, вероятно, захотите удалить пункт меню Page Explorer, поскольку он немного избыточен. Я также рекомендую реализовать метод 2, приведенный ниже. Даже если вы удалите пункт меню Page explorer, пользователь, возможно, сможет попасть туда, введя URL-адрес непосредственно в браузере. Если они это сделают, реализация метода 2 гарантирует, что они не увидят контент, созданный другими пользователями.

Способ 2: construct_explorer_page_queryset @hooks

Информация о хукле в документации Wagtail — construct_explorer_page_queryset также ссылается на эту статью Google Groups — https://groups.google.com/forum /#!topic/wagtail/10tcq8PB8io

В том же wagtail_hooks.py-файл, который я создал выше, я добавил этот код:

 @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
  

Вот и все для второго метода.

Комментарии:

1. В вашем get_queryset() не могли бы вы фильтровать страницы по qs.filter(owner=request.user) ?

2. Спасибо @KalobTaulien за предложение. Это не только работает, но и требует меньше кода и исключает добавление ненужного поля в базу данных. Я обновил приведенный выше код, чтобы отразить ваши предложения.

Ответ №2:

@Pahikua имейте в виду, что метод 2 просто скрывает страницы из списка и не защищает страницы от редактирования и удаления. В вашем случае это означает, что Автор1 может открыть URL типа pages/id / edit / где id — идентификатор страницы, принадлежащей Автору2, и отредактировать ее.

Чтобы избежать этого, вы должны добавить крючки before_edit_page и before_delete_page. Что-то вроде этого:

 @hooks.register('before_edit_page')
def before_edit_page(request, page):
    user_group = request.user.groups.filter(name='Author').exists()
    if user_group and page.owner != request.user:
        raise PermissionDenied
  

Ответ №3:

Спасибо @Pahikua и @Igor Margitich. Я смог объединить их ответы в красивую компоновку, которая была именно тем, что я хотел.

  1. Создайте пункт меню администратора для статьи (или для любой другой модели, с которой вы хотите, чтобы ваши авторы могли работать), как предложено @Pahikua в его методе 1. Это даст авторам ярлык для быстрого перехода к своему контенту (или даже добавления контента отсюда).
  2. Я не удалял пункт меню администратора Page Explorer, поскольку я действительно хотел, чтобы мои авторы могли перемещаться по страницам других авторов, чтобы перейти в нужное место для добавления своей страницы.
    В противном случае добавление страниц в нужное место только из вновь созданного пункта меню статьи (на шаге 1) было очень громоздким.
  3. Добавьте эти хуки «до», как предложил @Igor Margitich. Я также использовал хук before_create_page, поскольку хотел, чтобы мои авторы могли добавлять страницы только одного типа.
 from wagtail.core import hooks
from django.core.exceptions import PermissionDenied
from django.views.defaults import permission_denied
from .models import Article

@hooks.register('before_edit_page')
def before_edit_page(request, page):
    # user_group = request.user.groups.filter(name='Author').exists() # I did not use user_group
    if not (request.user.is_superuser or page.owner == request.user):
        return permission_denied(request, PermissionDenied("You do not have permission to edit this page."))
    
@hooks.register('before_delete_page')
def before_delete_page(request, page):
    if not (request.user.is_superuser or page.owner == request.user):
        return permission_denied(request,PermissionDenied("You do not have permission to delete this page."))
    
@hooks.register('before_create_page')
def before_create_page(request, parent_page, page_class):
    if not (request.user.is_superuser or page_class == Article):
        return permission_denied(request, PermissionDenied("You do not have permission to add this page."))