将标签放入 StructBlock

Jos*_*ock 1 tags django django-models wagtail

我希望能够向我创建的自定义 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'

Run Code Online (Sandbox Code Playgroud)

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'
    )

Run Code Online (Sandbox Code Playgroud)

如何允许块具有元数据标记?

LB *_*ton 6

基于自定义块类型的文档作为起点,我们能够生成FieldBlock利用现有 Wagtail的自定义AdminTagWidget

这个小部件几乎可以为您完成所有工作,它将拉入自动完成的可用标签,并保存动态创建的任何新标签。

可以读出这些标签并通过模型@property或类似物更方便地使用它们。请记住,Streamfields 将数据存储为 JSON,因此您不会获得任何开箱即用的模型/数据库链接。

限制

需要注意的是,保存的标签存储为原始字符串,这意味着如果您有一些更复杂的标签用例,您将需要做更多的工作来集成它。例如一个标签页面,显示所有使用该标签的页面或 Wagtail 中的高级标签编辑ModelAdmin

在这些情况下,您可以找到一种方法将 Page 的标签与 StreamField 标签“同步”,也可以将此工作抽象为 mixin。或者,您可以在标签页面上重新处理查询,以将那些包含所需流场数据的内容也包括在内。

示例代码

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


Run Code Online (Sandbox Code Playgroud)

感谢这个关于流场中标签的类似问题,回答帮助我回答了这个问题。 为 StreamField 创建一个标签块