问题描述
我正在使用由
post_body = markdown(text_from_markdown_editor)
但是当我渲染 html 时,会显示实际的 jinja2 代码
but when i render the html, the actual jinja2 code is displayed
This is a post by {{ post.author }}
而不是实际值.
推荐答案
我最近在各个不同的地方经常看到这个问题,包括 Jinja 和 Django 模板.关于模板系统的工作原理以及它与呈现为 HTML 并插入到模板中的 Markdown 文本的关系,似乎存在根本性的误解(在一些用户中).我会尽力解释清楚.请注意,虽然下面的答案适用于大多数模板系统(包括 Jinja 和 Django),但这些示例使用 Jinja 进行说明(毕竟,原始问题专门询问 Jinja).只需调整代码以匹配您选择的模板系统的 API,它应该也能正常工作.
I've been seeing this issue come up a lot lately in various different places, both in relation to Jinja and Django Templates. There seems to be a fundamental misunderstanding (among some users) about how templates systems work and how that relates to Markdown text which is rendered to HTML and inserted into a template. I’ll try to explain this clearly. Note that while the answer below applies to most templating systems (including Jinja and Django), the examples use Jinja for illustrative purposes (after all, the original question specifically asks about Jinja). Simply adapt the code to match the API of your templating system of choice, and it should work just as well.
首先,Markdown 对模板语法一无所知.事实上,Markdown 比 Jinja、Django 或其他各种流行的模板系统存在的时间更长.此外,Markdown 语法规则 没有提及模板语法.因此,您的模板语法不会简单地通过通过 Markdown 解析器传递一些包含模板语法的 Markdown 文本来处理.模板语法需要由模板引擎单独处理.例如:
First of all, Markdown has no knowledge of template syntax. In fact, Markdown has been around longer than Jinja, Django or various other popular templating systems. Additionally, the Markdown Syntax Rules make no mention of template syntax. Therefore, your template syntax will not be processed simply by passing some Markdown text which contains template syntax through a Markdown parser. The template syntax needs to be processed separately by the template engine. For example:
from jinja2 import Environment
# Set up a new template environment
env = Environment()
# Create template with the markdown source text
template = env.from_string(text_from_markdown_editor)
# Render that template. Be sure to pass in the context (post in this instance).
template_processed_markdown = template.render(post=post)
# Now pass the Markdown text through the Markdown engine:
post_body = markdown(template_processed_markdown)
注意上面先处理模板语法,然后解析Markdown.换句话说,模板处理的输出仍然是标记为适当值替换的标记文本.只有最后一行是 Markdown 解析器将 Markdown 文本转换为 HTML.如果您想颠倒处理顺序,则需要切换代码以先运行 Markdown 解析器,然后将其输出传递给模板处理器.
Note that the above first processes the template syntax, then parses the Markdown. In other words, the output of the template processing is still Markdown text with the tags replaced by the appropriate values. Only in the last line is the Markdown text converted to HTML by the Markdown parser. If you want the order of processing to be reversed, you will need to switch the code around to run the Markdown parser first and then pass the output of that through the template processor.
我认为一些混乱来自人们通过模板系统传递 Markdown 文本.这不应该导致模板语法被处理吗?总之,没有.
I assume that some of the confusion comes from people passing the Markdown text through a templating system. Shouldn’t that cause the template syntax to get processed? In short, No.
模板系统的核心是一个模板和一个上下文.然后它在模板中找到各种标签,并用上下文中提供的匹配数据替换这些标签.但是,模板不了解上下文中的数据,也不处理该数据.例如,这个模板:
At its core, a templating system takes a template and a context. It then finds the various tags in the template and replaces those tags with the matching data provided in the context. However, the template has no knowledge about the data in the context and does no processing of that data. For example, this template:
Hello, {{ name }}!
还有这个上下文:
output = template(name='John')
将导致以下输出:
Hello, John!
但是,如果上下文是这样的:
However, if the context was this instead:
output = template(name='{(some_template_syntax)}')
那么输出将是:
Hello, {{some_template_syntax}}!
请注意,虽然上下文中的数据包含模板语法,但模板并未处理该数据.它只是将其视为一个值并将其按原样插入模板的适当位置.这是正常且正确的行为.
Note that while the data in the context contained template syntax, the template did not process that data. It simply considered it a value and inserted it as-is into the template in the appropriate location. This is normal and correct behavior.
但是,有时您可能需要一个模板来对传递给模板的某些数据进行一些额外的处理.因此,模板系统提供了过滤器.当给定上下文中的变量时,过滤器将处理该变量中包含的数据,然后将处理后的数据插入模板中.例如,为确保前面示例中的名称大写,模板应如下所示:
Sometimes however, you may have a legitimate need for a template to do some additional processing on some data passed to the template. For that reason, the template system offers filters. When given a variable in the context, the filter will process the data contained in that variable and then insert that processed data in the template. For example, to ensure that the name in our previous example is capitalized, the template would look like the following:
Hello, {{ name|capatalize }}!
传入上下文output = template(name='john')
(注意名字是小写的),我们得到如下输出"
Passing in the context output = template(name='john')
(note that the name is lowercase), we then get the following output"
Hello, John!
注意,name
变量中的数据是通过首字母大写处理的,这是Jinja内置过滤器的作用capitalize
.但是,该过滤器不处理模板语法,因此将模板语法传递给该过滤器不会导致处理模板语法.
Note, that the data in the name
variable was processed by having the first letter capitalized, which is the function of Jinja’s built-in filter capitalize
. However, that filter does not process template syntax, and therefore passing template syntax to that filter will not cause the template syntax to be processed.
同样的概念适用于任何 markdown
过滤器.此类过滤器仅将提供的数据解析为 Markdown 文本并返回 HTML 文本,然后将其放入模板中.在这种情况下不会发生模板语法的处理.事实上,这样做可能会导致安全问题,特别是如果 Markdown 文本是由不受信任的用户提供的.因此,任何包含模板语法的 Markdown 文本都必须单独处理模板语法.
The same concept applies to any markdown
filter. Such a filter only parses the provided data as Markdown text and returns HTML text which is then placed into the template. No processing of template syntax would happen in such a scenario. In fact, doing so could result in a possible security issue, especially if the Markdown text is being provided by untrusted users. Therefore, any Markdown text which contains template syntax must have the template syntax processed separately.
但是,有一个注意事项.如果您正在编写包含模板语法示例作为代码块的文档(如本答案的 Markdown 源代码),模板系统不会知道其中的区别,并且会像处理不在代码中的任何模板语法一样处理这些标签堵塞.如果首先完成 Markdown 处理,以便将生成的 HTML 传递给模板系统,则该 HTML 仍将在代码块中包含未更改的模板语法,这些代码块仍将由模板系统处理.这很可能不是两种情况下所希望的.作为一种解决方法,可以想象创建某种 Markdown 扩展,将语法处理添加到 Markdown 处理器本身.但是,这样做的机制会因所使用的 Markdown 处理器而异,并且超出了本问题/答案的范围.
However, there is a note of caution. If you are writing documentation which includes examples of Template syntax in them as code blocks (like the Markdown source for this answer), the templating system is not going to know the difference and will process those tags just like any template syntax not in a code block. If the Markdown processing was done first, so that the resulting HTML was passed to the templating system, that HTML would still contain unaltered template syntax within the code blocks which would still be processed by the templating system. This is most likely not what is desired in either case. As a workaround, one could conceivably create some sort of Markdown Extension which would add syntax processing to the Markdown processor itself. However, the mechanism for doing so would differ depending on which Markdown processor one is using and is beyond the scope of this question/answer.
这篇关于你如何在 Markdown 文件中包含 Flask/jinja2 代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!