0

我对Wagtail真的很陌生。我一直在尝试找到一种方法来过滤选择器(PageChooserPanel)中的值。我正在建立一个故事网站,作者可以在其中创建非线性故事。我遵循一个博客模型来构建它并对其进行扩展。我已经到了作者可以通过可订购链接链接页面的地步。问题是其他故事的可订购显示页面。有没有办法过滤掉不相关的页面。我很感激这方面的任何帮助。先感谢您!

这是我的代码:

class StoryPath(models.Model):
    route = models.ForeignKey('story.StoryPage', on_delete=models.SET_NULL, null=True, related_name='next_path', verbose_name='Story Path')
    
    panels = [
        PageChooserPanel('route', page_type='story.StoryPage'),
        FieldPanel('correct'),
    ]

    class Meta:
        abstract = True

class StoryPathOrderable(Orderable, StoryPath):
    page = ParentalKey('story.StoryPage', on_delete=models.CASCADE, related_name='story_paths')

class StoryPage(Page):
    template = 'story/story_page.html'
    body = RichTextField()
    
    content_panels = [
        FieldPanel('title', heading='Section Title', classname='collapsible'),
        FieldPanel('body', classname='collapsible'),
        MultiFieldPanel(
            [
                InlinePanel('story_paths'),
            ],
            heading = 'Story Paths',
            classname = 'collapsible'
        )
    ]
    parent_page_type =['story.Story']
    subpage_types = []

    def __str__(self):
        return '%s' % (self.title)

class Story(Page):
    subtitle = models.CharField(max_length=250, null=True, blank=True)
    
    content_panels = Page.content_panels + [
        FieldPanel('subtitle'),
    ]

    subpage_types = ['story.StoryPage']

    def __str__(self):
        return '%s' % (self.title)

编辑:这是我正在使用的模板:

{% extends "base.html" %}
{% load static wagtailcore_tags %}

{% block body_class %}{{self.title}}{% endblock %}

{% block extra_css %}{% endblock extra_css %}

{% block content %}
    <div class="d-flex justify-content-center flex-column">
        <div class="fs-3">{{page.title}}</div>
        <div>{{page.body|richtext}}</div>
    </div>
{% endblock content %}
4

1 回答 1

0

PageChooserPanel使用, 打开带有搜索界面的模式并不容易,但是如果您对字段仅显示“兄弟”页面的下拉菜单感到满意,那么您可以更轻松地实现此目标。

对这一切如何运作的一些概述;

  • 当你使用InlinePanel('story_paths'),它时,它会利用 Wagtail、Django 和Django Modelcluster的一些部分来设置动态表单集。
  • 允许您为类似对象的InlinePanel多个添加创建子“表单”,在这种情况下,内联创建的对象是StoryPathOrderable实例。
  • 当您使用InlinePanel它时,它将查找panels正在创建/管理的内部模型的属性。
  • 在您的内部模型上,您已经设置了PageChooserPanel('route', page_type='story.StoryPage'),.
  • PageChooserPanel对于很多用例来说确实很棒,但对于边缘情况有点难以定制(因为它创建了一个字段来触发具有自己的搜索/列表界面的模式)。可以使用 Wagtail Hooks 修改此模式的结果 - 请参阅`construct_page_chooser_queryset',但是这是全局的,无法知道“哪个”页面或字段正在请求链接页面。
  • 但是,我们不必使用PageChooserPanel,您可以使用FieldPanel提供整个应用程序可用页面下拉列表的基本功能,从那里我们可以更轻松地自定义此字段的查询。
  • 如果您想对此进行更多控制并希望保留模态界面,您可以使用Wagtail Generic Chooser来查看。

例子

  • 下面我们将创建一个自定义FieldPanel来修改其 的行为,on_form_bound一旦表单可用,就会在为编辑器构建表单时调用它。
  • 从这里我们可以找到该页面列表字段的字段并将其查询集修改为所需的结果。
  • page = self.page当您不使用时将起作用,InlinePanel因为实例将是当前编辑的页面。
  • 但是,对于InlinePanel,我们需要考虑将“初始”表单准备为模板的情况,以便您可以动态添加项目。
  • 为了处理InlinePanel基本字段的使用,我们可以获取绑定到自定义面板实例的当前请求并从那里推断页面。
  • 一旦我们可以访问权限Page和字段,我们就可以修改查询集以满足我们的需要,Wagtail 扩展了查询集添加child_ofsibling_of的能力。

some-app/models.py

from wagtail.admin.edit_handlers import FieldPanel



class SiblingOnlyPageFieldPanel(FieldPanel):
    def on_form_bound(self):
        super().on_form_bound()

        field = self.form[self.field_name].field

        # when creating a new page, check for the parent page ID & refine field queryset
        parent_page_id = self.request.resolver_match.kwargs.get("parent_page_id", None)
        if parent_page_id:
            parent_page = Page.objects.filter(pk=parent_page_id).first()
            field.queryset = field.queryset.child_of(parent_page)
            return

        # when editing a page, get the ID of the page currently being edited
        page_id = self.request.resolver_match.kwargs.get("page_id", None)
        if not page_id:
            return

        page = Page.objects.filter(pk=page_id).first()
        if not page:
            return

        field = self.form[self.field_name].field
        field.queryset = field.queryset.sibling_of(page)



class StoryPath(models.Model):
    route = models.ForeignKey('story.StoryPage', on_delete=models.SET_NULL, null=True, related_name='next_path', verbose_name='Story Path')
    
    panels = [
        SibingOnlyPageFieldPanel('route'), # replaced PageChooserPanel & removed `page_type` as that will no longer work for a normal FieldPanel
        FieldPanel('correct'),
    ]

    class Meta:
        abstract = True
于 2021-11-14T22:05:18.890 回答