【问题标题】:Accessing Subpage Model properties in template file Wagtail访问模板文件 Wagtail 中的子页面模型属性
【发布时间】:2016-04-21 08:11:59
【问题描述】:

这是我的 model.py 文件

...

class LinkFields(models.Model):
    link_external = models.URLField(
        "External link",
        blank=True,
        null=True,
        help_text='Set an external link if you want to describe the event from an other web site',
    )
    link_page = models.ForeignKey(
        'wagtailcore.Page',
        null=True,
        on_delete=models.SET_NULL,
        blank=True,
        related_name='+',
        help_text='Choose an existing page (event must have already been created)',
    )

    @property
    def link(self):
        if self.link_page:
            return self.link_page.url
        else:
            return self.link_external

    panels = [
        FieldPanel('link_external'),
        PageChooserPanel('link_page'),
    ]

    class Meta:
        abstract = True

class RelatedLink(LinkFields):
    title = models.CharField(max_length=255, help_text="Link title")

    panels = [
        FieldPanel('title'),
        MultiFieldPanel(LinkFields.panels, "Link"),
    ]

    class Meta:
        abstract = True


class HomePage(Page):
    body = RichTextField(blank=True)

    content_panels = Page.content_panels + [
        FieldPanel('body', classname="full"),
        InlinePanel('related_links', label="Related events"),
    ]


class EventsPage(Page):

    # Database fields

    date = models.DateField("Event date")
    topicTag = models.CharField(max_length = 25)
    name = models.CharField(max_length = 50)
    city = models.CharField(max_length = 20, default="Where it is")
    place = models.CharField(max_length = 20, blank=True)
    body = RichTextField(blank=True)

    # Search index configuration

    search_fields = Page.search_fields + (
        index.SearchField('topicTag'),
        index.SearchField('place'),
        index.FilterField('date'),
    )

    # Editor panels configuration

    content_panels = Page.content_panels + [
        FieldPanel('date'),
        FieldPanel('topicTag'),
        FieldPanel('name', classname="title"),
        FieldPanel('city'),
        FieldPanel('place'),
        FieldPanel('body'),
    ]


class EventsRelatedLink(Orderable, RelatedLink):
    page = ParentalKey('HomePage', related_name='related_links')

EventsPages 是 HomePage 的子页面,HomePage 本身显示后续子页面的链接。我的问题是对于我在主页上显示的每个子页面的链接,我想访问所谓的子页面的属性以显示一种预览。

这是我的 home_page.html 模板:

{% extends "base.html" %}

{% load wagtailcore_tags %}

{% block body_class %}template-homepage{% endblock %}

{% block content %}
   <h1>THE <span class="pink">OPEN SOURCE</span> INNOVATION SPRING</h1>

   <div class="intro">{{ page.body|richtext }}</div>

   {% if page.related_links.all %}
      <ul>
    {% for item in page.related_links.all %}
       <li><a href="{{ item.link }}">{{ item.title }}</a></li>
       <br><div class="description">{{ item.date }}
         <span class="pink">[{{ item.topicTag }}]</span>
          {{ item.name }} <span class="pink">[{{ item.city }}]</span>
       </div>
    {% endfor %}
      </ul>
   {% endif %}
{% endblock %}

当然,所有带有 * 作为 EventsPage 模型属性的“item.*”都不起作用。我很确定我走错了路,但我需要帮助才能做到这一点。

【问题讨论】:

    标签: python-2.7 wagtail


    【解决方案1】:

    首先,{{ item.date }} 不起作用,因为item 是RelatedLink 对象,而不是页面对象。要访问页面对象,您需要{{ item.link_page.date }}(当然,当编辑器提供link_external 而不是link_page 时,还有一些替代行为)。但是,仅此更改还不够 - 它适用于 item.link_page.title 等核心页面属性,但不适用于 date 等特定于事件的属性。

    解释为什么会发生这种情况:每当您检索一组页面时,通过EventPage.objects.all()、page.get_children() 或(在本例中)page.related_links 之类的操作,通常所有结果都是相同的类型。如果它是一个可能覆盖几种不同类型页面的操作(例如 - EventPage.objects.all() 只能返回 EventPage 对象,但 page.get_children() 或 page.related_links 可以返回任何类型的页面),那么为了保持它们全部同样,它必须将它们作为“最小公分母”返回——所有页面类型都源自的基本页面模型。这提供了所有页面通用的字段,例如title,但没有任何特殊用途的字段。

    (这是数据库查找工作方式的一个限制——如果我们想以最具体的形式获取每个页面对象,数据库查询必须同时检查所有与页面相关的表,这是非常低效的.)

    考虑到这一点,您可以选择以下几种方式:

    首先,如果您知道您网站上的编辑只会选择 EventPages 作为相关链接 - 根据您的 help_text 和您正在撰写的事实,这似乎是一个安全的假设{{ item.date }} 和 {{ item.city }} 之类的东西可能对其他类型的页面没有意义 - 然后您可以通过将外键指向 EventPage 在数据库级别强制执行此操作:

    link_page = models.ForeignKey(
        'myapp.EventPage',  # replace 'myapp' with your application name
        null=True,
        on_delete=models.SET_NULL,
        blank=True,
        related_name='+',
        help_text='Choose an existing page (event must have already been created)',
    )
    

    进行此更改后,Wagtail 管理员中的页面选择器将只允许您为此字段选择 EventPages,item.link_page 将为您提供完整的 EventPage 对象,允许您编写 {{ item.link_page.date }} .

    其次:如果您需要在相关链接中支持其他页面类型 - 例如,也许您有一个 NewsPage 模型也有一个 date 字段,并且希望能够选择这些作为相关链接- 然后您可以通过调用.specific 将基本的Page 对象转换为更具体的页面类型。例如:{{ item.link_page.specific.date }}。缺点是.specific 每次使用时都会执行额外的数据库查找,这可能会损害性能。作为一个简单的优化,您可以使用 {% with %} 标签将其分配给变量:

    {% for item in page.related_links.all %}
       {% with item.link_page.specific as related_page %}
          <li><a href="{{ item.link }}">{{ item.title }}</a></li>
          <br><div class="description">{{ related_page.date }}
            <span class="pink">[{{ related_page.topicTag }}]</span>
             {{ related_page.name }} <span class="pink">[{{ related_page.city }}]</span>
          </div>
       {% endwith %}
    {% endfor %}
    

    【讨论】:

    • 它解决了我的问题,你让我更准确地理解它是如何工作的。非常感谢
    猜你喜欢
    • 2021-10-09
    • 2019-01-21
    • 1970-01-01
    • 2011-11-29
    • 2020-05-03
    • 1970-01-01
    • 2017-07-21
    • 1970-01-01
    • 2020-03-20
    相关资源
    最近更新 更多