Wagtail:如何在StructBlock模板访问Page对象及优化方案
解决方案
一、将Page对象传入Block模板的方法
你需要在自定义的ProgramEntryBlock中重写get_context方法,从父上下文(页面渲染时的上下文)中提取page对象并传递给Block模板:
from wagtail.core import blocks from django.utils.translation import gettext_lazy as _ class ProgramEntryBlock(blocks.StructBlock): class Meta: label = _("Program entry") template = "blocks/program-entry-block.html" def get_context(self, value, parent_context=None): # 获取Block基础上下文 context = super().get_context(value, parent_context=parent_context) # 从父上下文提取page对象并注入当前上下文 if parent_context and 'page' in parent_context: context['page'] = parent_context['page'] return context
修改后,blocks/program-entry-block.html模板就能直接使用page变量,访问关联的program_entries数据了。
二、更优的实现方案
由于你的ProgramEntryBlock不需要编辑者输入任何内容(仅用来展示已关联的节目单条目),用StructBlock存在冗余,更合适的做法是直接继承blocks.Block,简化Block定义:
class ProgramEntryBlock(blocks.Block): class Meta: label = _("Program entry") template = "blocks/program-entry-block.html" def get_context(self, value, parent_context=None): context = super().get_context(value, parent_context=parent_context) if parent_context and 'page' in parent_context: context['page'] = parent_context['page'] return context # 无需存储值,返回空默认值 def get_default(self): return None # 渲染空表单(因为不需要编辑内容) def render_form(self, value, prefix='', errors=None): return ''
同时确保ProgramEntry模型的关联逻辑正确:
from django.db import models from wagtail.core.models import Page from modelcluster.fields import ParentalKey class ProgramEntry(models.Model): page = ParentalKey('your_app.Event', related_name='program_entries', on_delete=models.CASCADE) title = models.CharField(max_length=255, verbose_name="节目名称") start_time = models.TimeField(verbose_name="开始时间") description = models.TextField(verbose_name="节目描述", blank=True) class Meta: ordering = ['start_time'] # 按时间排序节目单
最后在Event页面模型的StreamField中添加该Block:
from wagtail.core.fields import StreamField from wagtail.admin.panels import StreamFieldPanel class Event(Page): body = StreamField([ ('program', ProgramEntryBlock()), # 其他你需要的Block类型,比如文本、图片等 ], use_json_field=True) content_panels = Page.content_panels + [ StreamFieldPanel('body'), ]
这样编辑者就能在Event页面的StreamField中任意位置插入节目单模块,模板也能正确渲染关联的节目条目。
内容的提问来源于stack exchange,提问作者moddayjob
相关产品推荐
相关产品推荐

