渲染片段
• 最后修改:2024-05-05 • 阅读量:42
作为 Django 模型,片段可以在 Django 模板中使用自定义模板标签来呈现。或者,它们也可以作为 Wagtail 页面渲染过程的一部分。
在模板标签中包含片段
使片段可用于模板的最简单方法是使用模板标签。这主要是使用 vanilla Django 完成的,因此查看 自定义 template tags 的 Django 文档可能会更有帮助。不过,我们将回顾一下基础知识,并指出对 Wagtail 的任何注意事项。
首先,将新的 python 文件添加到应用程序内的 templatetags
文件夹中 - 例如 myproject/demo/templatetags/demo_tags.py
。我们需要加载一些 Django 模块和我们应用程序的模型,并准备好 register
装饰器:
from django import template
from demo.models import Advert
register = template.Library()
# ...
# 广告片段
@register.inclusion_tag('demo/tags/adverts.html', takes_context=True)
def adverts(context):
return {
'adverts': Advert.objects.all(),
'request': context['request'],
}
@register.inclusion_tag()
采用两个变量:一个模板和一个关于是否应向该模板传递请求上下文的 boolean 。在自定义模板标签中包含请求上下文是一个好主意,因为一些特定于 Wagtail 的模板标签(如 pageurl
)需要上下文才能正常工作。模板标签函数可以接受参数并过滤广告以返回模型的特定实例,但为了简洁起见,我们将仅使用 Advert.objects.all()
。
以下是此模板标记使用的模板中的内容:
{% for advert in adverts %}
<p>
<a href="{{ advert.url }}">
{{ advert.text }}
</a>
</p>
{% endfor %}
然后,在您自己的页面模板中,您可以包含片段模板标记:
{% load wagtailcore_tags demo_tags %}
...
{% block content %}
...
{% adverts %}
{% endblock %}
将页面绑定到片段
在上面的示例中,广告列表是一个固定列表,通过自定义模板标签显示,独立于页面上的任何其他内容。这可能是您想要的侧边栏中的公共面板,但是,在另一种情况下,您可能希望在特定页面上仅显示代码片段的一个特定实例。这可以通过在页面模型中定义片段模型的外键并将 [FieldPanel
] 添加到页面的 content_panels
列表来完成。例如,如果您想在 BookPage
实例上显示特定广告:
# ...
class BookPage(Page):
advert = models.ForeignKey(
'demo.Advert',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
content_panels = Page.content_panels + [
FieldPanel('advert'),
# ...
]
然后可以在模板中以 page.advert
的形式访问该代码段。
要将多个广告附加到页面, FieldPanel
可以放置在 BookPage
的内联子对象上,而不是放置在 BookPage
本身上。在这里,这个子模型被命名为 BookPageAdvertPlacement
(之所以这样称呼是因为每次在 BookPage 上放置广告时都会有一个这样的对象):
from django.db import models
from wagtail.models import Page, Orderable
from modelcluster.fields import ParentalKey
# ...
class BookPageAdvertPlacement(Orderable, models.Model):
page = ParentalKey('demo.BookPage', on_delete=models.CASCADE, related_name='advert_placements')
advert = models.ForeignKey('demo.Advert', on_delete=models.CASCADE, related_name='+')
class Meta(Orderable.Meta):
verbose_name = "advert placement"
verbose_name_plural = "advert placements"
panels = [
FieldPanel('advert'),
]
def __str__(self):
return self.page.title + " -> " + self.advert.text
class BookPage(Page):
# ...
content_panels = Page.content_panels + [
InlinePanel('advert_placements', label="Adverts"),
# ...
]
现在可以通过页面的 advert_placements
属性访问这些子对象,并且从那里我们可以将链接的 Advert
代码段作为 advert
访问。在 BookPage
的模板中,我们可以包含以下内容:
{% for advert_placement in page.advert_placements.all %}
<p>
<a href="{{ advert_placement.advert.url }}">
{{ advert_placement.advert.text }}
</a>
</p>
{% endfor %}