Размещение тегов в StructBlock - PullRequest
0 голосов
/ 15 апреля 2020

Я хочу иметь возможность добавлять теги к созданному мной пользовательскому StructBlock.

Текущая модель выглядит следующим образом

class MapsIndicatorBlock(blocks.StructBlock):

    text_icon = blocks.CharBlock(
        label='Maps/Indicators Text or Icon',
        required=False
    )

    pop_up_title = blocks.CharBlock(
        label='Pop-Up Title',
        required=False
    )

    pop_up_text = blocks.RichTextBlock(
        label ='Pop-Up Text/Image',
        required=False
    )

    pop_up_colour = blocks.CharBlock(
        choices=constants.BOOTSTRAP4_BUTTON_COLOUR_CHOICES,
        default='btn btn-primary',
        max_length=128,
        required=False
    )

    tags = TaggableManager()

    objects = models.Manager()

    class Meta:
        template = 'cityregiontable/map_indicator_block.html'

TaggableManager () был разработан для использования с models.model, а не blocks.StructBlock.

Я пытался создать способ создания тегов, используя следующие, но безрезультатно. Я получаю ошибку RE: не удается найти модель для MapsIndicatorBlock. Это правильно, поскольку MapsIndicatorBlock - это блок, а не модель.

class MITag(TaggedItemBase):
    content_object = models.ForeignKey(
        'MapsIndicatorBlock',
        on_delete=models.CASCADE,
        related_name='tagged_mi_block'
    )

Как разрешить блоку иметь теги метаданных?

1 Ответ

3 голосов
/ 17 апреля 2020

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

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

Можно считывать эти теги и делать их доступно более удобно с моделью @property или аналогичной. Помните, что Streamfields хранит данные как JSON, поэтому вы не получите никаких ссылок на модель / базу данных из коробки.

Ограничения

Предупреждение: сохраненные теги сохраняются как необработанные strings, это означает, что если у вас есть более сложные варианты использования тегов, вам придется проделать немного больше работы, чтобы интегрировать их. например, страница тега, которая показывает все страницы, которые используют этот тег или расширенное редактирование тега в Wagtail ModelAdmin.

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

Пример кода

from itertools import chain

from django import forms

from wagtail.admin.edit_handlers import FieldPanel, StreamFieldPanel
from wagtail.admin.widgets import AdminTagWidget

from wagtail.core.blocks import CharBlock, FieldBlock, StructBlock, RichTextBlock
from wagtail.core.fields import StreamField
from wagtail.core.models import Page

class TagsBlock(FieldBlock):
    """
    Basic Stream Block that will use the Wagtail tags system.
    Stores the tags as simple strings only.
    """

    def __init__(self, required=False, help_text=None, **kwargs):
        # note - required=False is important if you are adding this tag to an existing streamfield
        self.field = forms.CharField(widget=AdminTagWidget, required=False)
        super().__init__(**kwargs)


class MapBlock(StructBlock):
    title = CharBlock(label="Title", required=False)
    content = RichTextBlock(label="Content", required=False)
    tags = TagsBlock(label="Tags", required=False)

    class Meta:
        icon = 'site'


class LocationPage(Page):
    """
    Detail for a specific location.
    """

    # ... other fields

    # this is the stream field added
    map_info = StreamField([('Map', MapBlock(required=False))], blank=True)

    @property
    def get_tags(self):
        """
        Helpful property to pull out the tags saved inside the struct value
        Important: makes some hard assumptions about the names & structure
        Does not get the id of the tag, only the strings as a list
        """

        tags_all = [block.value.get('tags', '').split(',') for block in self.test_b]

        tags = list(chain.from_iterable(tags_all))

        return tags

    # Fields to show to the editor in the admin view
    content_panels = [
        FieldPanel('title', classname="full"),
        StreamFieldPanel('map_info'),
        # ... others
    ]

    # ... rest of page model


Благодаря этот похожий вопрос о тегах в streamfields , отвечая, что помог мне ответить на этот. Создание блока тегов для StreamField

...