Как скопировать конфиденциальность страницы в блок в трясогузке? - PullRequest
0 голосов
/ 28 апреля 2020

Страницы имеют эту настройку конфиденциальности, в которой можно указать, кому разрешено просматривать определенную страницу.

В моей документации требуется немного более детальный рычаг, где для определенного блока c можно также ограничить его. visibility.

Я был бы вполне доволен выбором групп, но, очевидно, я не могу поместить ManyToManyRelation в модель страницы. Скорее я бы сделал это в блоке, который мне нужно обработать.

Поэтому я попытался определить блок следующим образом:

class MyBlock(StructBlock):
    visible_groups = ListBlock(ChooserBlock(
        label=_('Limit view to groups'), target_model='django.contrib.auth.groups', 
        required=False, blank=True
    ))

Но Wagtail жалуется, что ChooserBlock был объявлен без атрибута target_model. Я предполагаю, что отсутствие конструктора, делающего это, является достаточным показателем того, что сам ChooserBlock не предназначен для таких операций.

Как я могу правильно объявить свой Блок, чтобы я мог выбрать группы, а затем - при рендеринге - правильно идентифицировать их и сопоставить их с группами пользователей?

1 Ответ

2 голосов
/ 29 апреля 2020

ChooserBlock не предназначен для использования автономно, а является базовым классом, предназначенным для создания других типов выбора.

Опция 0 - использование связанной модели

  • Хотя я понимаю ваше желание не использовать отношения модели, вы можете в конечном итоге создать большую сложность, пытаясь использовать StreamFields здесь.
  • Возможно, стоит переосмыслить проблему в условия базовых c отношений, ваша страница представляет собой список элементов контента, каждый элемент контента имеет отношение один ко многим к группе аутентификации И имеет некоторый контент (форматированный текст и т. д. c).
  • Вы могли бы сделать это с обычной моделью, которая относится к вашей странице, и с помощью InlinePanel Wagtail позволяет пользователю создавать многие из этих элементов контента, каждый из которых имеет свой собственный набор групп аутентификации и содержимое. Помните, что внутреннее содержимое в других моделях все еще может быть основано на StreamField, но основные соединения в этом методе будут нормальными Django отношениями.
  • Помните, что ссылки StreamField не так надежны (например, если группы аутентификации удаляются, ссылки могут стать устаревшими в вашем StreamField, и нет простых способов заблокировать это), плюс миграции становятся довольно сложными, если вы хотите что-то еще изменить в будущем.

Вариант 1 - Использование SnippetChooser

Самый быстрый способ получить эту работу - использовать SnippetChooserBlock и зарегистрировать Django аутентификационные группы как фрагмент . Одним из предостережений к этому подходу является то, что модель будет отображаться в меню ваших фрагментов (если включено) в пользовательском интерфейсе администратора.

Во-первых, зарегистрируйте модель как фрагмент где-то в центре (например, wagtail_hooks.py)

from django.contrib.auth.models import Group
from wagtail.snippets.models import register_snippet

# ... other hooks things
register_snippet(Group)

Затем создайте свой пользовательский StructBlock, используя SnippetChooser, где бы вы ни хранили свои блоки.

from django.contrib.auth.models import Group
from wagtail.snippets.blocks import SnippetChooserBlock
from wagtail.core.blocks import ListBlock

class PrivacyBlock(StructBlock):
    visible_groups = ListBlock(
        SnippetChooserBlock(
            Group,
            label='Limit view to groups',
            required=False,
            blank=True
        )
    )

    class Meta:
        icon = "user"

Наконец, вы можете использовать это в своей PageModel, как и любой другой StructBlock.

from wagtail.admin.edit_handlers import FieldPanel, InlinePanel, StreamFieldPanel
from wagtail.core.fields import StreamField

from myapp.blocks import PrivacyBlock


class BlogPage(Page):
    # ... other fields

    privacy_content = StreamField([
        ('privacy', PrivacyBlock(blank=True))
    ])

    content_panels = Page.content_panels + [
        # ... other panels
        StreamFieldPanel('privacy_content'),
    ]

Вариант 2. Построение или использование обобщенной c модели. Выбор

. Вы можете расширить ChooserBlock, чтобы создать свой собственный выбор, но это быстро усложняется, поскольку вам также необходимо создать собственную модель. Chooser. Приведенный ниже код НЕ является полностью функциональным, но дает представление о том, что может понадобиться.

Если вы можете использовать дополнительные библиотеки, возможно, стоит посмотреть на добавление Wagtail Generi c Chooser, вот несколько быстрых Результаты от Google (я не использовал их).

Помните, что блок выбора задается c для реализаций StreamField, и выбор аналогичен определенный c тип Django виджета. Вам нужно будет собрать или получить оба, если вы хотите использовать StreamFields для этой реализации.

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

PO C (не функциональный) пример кода


from wagtail.admin.widgets import AdminChooser
from django.utils.functional import cached_property

class ModelChooser(AdminChooser):
    # ... implement __init__ etc


class AuthGroupBlock(ChooserBlock):

    @cached_property
    def target_model(self):
        from django.contrib.auth.models import Group
        return Group

    @cached_property
    def widget(self):
        return ModelChooser(self.target_model)


class PrivacyBlock(StructBlock):
    visible_groups = ListBlock(
        AuthGroupBlock(
            label='Limit view to groups',
            required=False,
            blank=True
        )
    )

    class Meta:
        icon = "user"


class PrivacyBlock(StructBlock):
    visible_groups = ListBlock(
        SnippetChooserBlock(
            Group,
            label='Limit view to groups',
            required=False,
            blank=True
        )
    )

    class Meta:
        icon = "user"

...