#wagtail
#wagtail
Вопрос:
Я создаю сайт wagtail, где пользователи могут зарегистрироваться, войти в wagtail admin и написать страницы статей для публикации. Есть ли перехват или возможный способ перехватывать и фильтровать данные в wagtail admin, чтобы пользователи видели только страницы статей, которые они сами создали?
На данный момент я настроил регистрацию пользователей в django-allauth, и пользователи могут успешно входить в систему. После регистрации срабатывает приемник user_signed_up, и пользователю назначается роль «Автор». В admin у авторов есть доступ только к добавлению статей. Статьи — это приложение со страницей индекса статьи и страницей статьи (в основном, блог и страница индекса блога). После входа в систему единственное, что они видят, это вкладку «Страницы» слева, щелчок по которой приводит их к списку «Статьи». Здесь они могут добавить страницу «Статья» и просмотреть свои статьи, созданные на данный момент.
В этом также заключается моя проблема. На странице списка статей пользователи могут видеть все статьи, созданные всеми пользователями на сайте. Они могут редактировать только свои собственные, что здорово, но в конечном итоге появятся сотни статей от других пользователей. Есть ли способ перехватить данные «Статей» до их отображения и отфильтровать их по текущему пользователю?
В результате перехвата этих данных каждый пользователь, вошедший в wagtail admin, будет знать только о созданных им страницах статей.
Большое спасибо, я впервые использую Wagtail, и пока мне это нравится.
Комментарии:
1. Я наткнулся на ModelAdmin в документах Wagtail, и это вполне может быть то, что я ищу: Документы Wagtail — ModelAdmin
Ответ №1:
Я обнаружил два разных решения этого вопроса.
- Внедрите ModelAdmin для создания пользовательского представления списка страниц вашей модели. Это позволяет вам создать совершенно новый пункт меню администратора и соответствующий вид списка. Этот метод более сложный, но предлагает больше контроля.
- Внедрите хук администратора 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. Я смог объединить их ответы в красивую компоновку, которая была именно тем, что я хотел.
- Создайте пункт меню администратора для статьи (или для любой другой модели, с которой вы хотите, чтобы ваши авторы могли работать), как предложено @Pahikua в его методе 1. Это даст авторам ярлык для быстрого перехода к своему контенту (или даже добавления контента отсюда).
- Я не удалял пункт меню администратора Page Explorer, поскольку я действительно хотел, чтобы мои авторы могли перемещаться по страницам других авторов, чтобы перейти в нужное место для добавления своей страницы.
В противном случае добавление страниц в нужное место только из вновь созданного пункта меню статьи (на шаге 1) было очень громоздким. - Добавьте эти хуки «до», как предложил @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."))