我一直在努力学习 Wagtail,使用StreamField
s 和 blocks 的复杂性让我头疼。遵循 Wagtail 文档和演示应用程序我没有遇到任何问题,但如果没有外部帮助,超越这些似乎是不可逾越的。
这是我正在尝试(并且失败)实现的目标。
在使用 Blog 应用程序时,我尝试对其进行扩展,以便StreamField
允许添加基于pygments的带有语法突出显示的代码块。源代码由自定义StructBlock
类(自然而然)管理,CodeBlock
并且是StreamField
. BlogPage
在 Wagtail 管理员中,我可以输入代码、使用的语言、要应用的突出显示样式以及是否显示行号。这一切都工作得很好,直到我想根据所选的突出显示样式为渲染模板选择附加样式表。以下是页面模板如何包含样式表:
{% block extra_css %}
{# This goes in the page <head> section #}
{% if has_code_block %}
{% if code_colorizer %}
<link rel="stylesheet" type="text/css" href="{% static 'css/highlight_{{ code_colorizer }}.css' %}">
{% else %}
<link rel="stylesheet" type="text/css" href="{% static 'css/highlight_default.css' %}">
{% endif %}
{% endif %}
{% endblock %}
在CodeBlock
render 方法中完成了它的工作(这个想法很感激 - 并且无耻地使用 - 在线)。在应用程序流程的这一点上,将突出显示样式添加到页面上下文为时已晚,因此我尝试在覆盖的 def get_context 函数中分解页面正文字段,但没有成功。我只是无法通过任何类成员访问底层 JSON 文本或访问数据BlogPage
。
有没有办法在从数据库加载数据之后和交给模板之前将突出显示样式添加到页面上下文?
这是我的基本博客页面:
class BlogPage(Page):
tags = ClusterTaggableManager(through=BlogPageTag, blank=True)
posted_date = models.DateField("Post date")
edited_date = models.DateField("Edited date", null=True, blank=True)
feed_image = models.ForeignKey('wagtailimages.Image', null=True, blank=True, on_delete=models.SET_NULL, related_name='+')
body = StreamField(BlogStreamBlock)
search_fields = Page.search_fields + [
index.SearchField('body')
]
subpage_types = []
parent_page_types = ['BlogIndexPage']
@property
def blog_index(self):
return self.get_ancestors().type(BlogIndexPage).last()
BlogPage.content_panels = [
FieldPanel('title', classname='full title'),
FieldPanel('posted_date'),
FieldPanel('edited_date'),
StreamFieldPanel('body'),
InlinePanel('related_links', label="Related links"),
]
BlogPage.promote_panels = Page.promote_panels + [
ImageChooserPanel('feed_image'),
FieldPanel('tags'),
]
这是我的BlogStreamBlock
班级的定义:
class BlogStreamBlock(StreamBlock):
subtitle = CharBlock(icon='title', classname='title')
abstract = RichTextBlock(icon='pilcrow')
paragraph = RichTextBlock()
aligned_image = ImageBlock()
source_code = CodeBlock()
quote = QuoteBlock()
最后,这是CodeBlock
课程:
class CodeBlock(StructBlock):
LANGUAGE_CHOICES = (
('aspx-cs', '.NET ASP/C#'),
('aspx-vb', '.NET ASP/VisualBasic'),
('csharp', '.NET C#'),
('fsharp', '.NET F#'),
('vbnet', '.NET VisualBasic'),
('ng2', 'Angular 2'),
('html+ng2', 'Angular 2 Html'),
('apache', 'Apache Config'),
('arduino', 'Arduino Sketch'),
('asm', 'Assembly'),
('bash', 'Bash Shell'),
('batch', 'Batch CMD File'),
('c', 'C'),
('cpp', 'C++'),
('cmake', 'CMake'),
('coffeescript', 'Coffee Script'),
('css', 'CSS'),
# ... and many, many more ...
('vhdl', 'Vhdl'),
('registry', 'Windows Registry'),
('xml', 'XML'),
('xml+php', 'XML/PHP'),
('xslt', 'XSLT'),
('yaml', 'Yaml'),
)
COLORIZER_CHOICES = (
('abap', 'Abap'),
('algol', 'Algol'),
('algol_nu', 'Algol Nu'),
# ... finish the list with all the highlight styles in the current version of pygments
('vs', 'Vs'),
('xcode', 'Xcode'),
)
language = ChoiceBlock(choices=LANGUAGE_CHOICES, classname='full')
colors = ChoiceBlock(choices=COLORIZER_CHOICES, classname='full')
code = TextBlock()
line_numbers = BooleanBlock(classname='full')
class Meta:
icon = 'code'
def render(self, value, context=None):
src = value['code'].strip('\n');
lang = value['language']
line_nos = value['line_numbers']
lexer = get_lexer_by_name(lang)
formatter = get_formatter_by_name('html', linenos='table' if line_nos else False, cssclass='codehilite', style='default',noclasses=False)
return mark_safe(highlight(src, lexer, formatter))