如何在Django的latex模板中正确设置变量

4

我希望通过django视图使用latex创建pdf。我创建了视图并设置了latex模板,除了一个问题,它都可以正常工作。当我在latex模板中放置变量时,必须在花括号周围使用空格,如下所示:

\somevalue{ {{variable}} }

否则Django将不会检查它是否作为变量。LaTeX语法检查器已经告诉我“周围有意图之外的空格}?!”。我可以通过视图将变量传递到模板中并创建pdf,但插入文本周围会有空格。有人有解决这个问题的想法吗?

1
这在指定路径时尤其麻烦。我尝试了{% spaceless %}\includegraphics[width=200pt]{ {{ logo_pdf }} } {% endspaceless %},但是spaceless只适用于HTML。这需要一个类似的自定义标签来适用于LaTeX。 - Antoine Pinsard
2个回答

3

根据一些谷歌研究,我建议将模板引擎切换到Jinja,它受Django支持并具有可配置的语法。 请注意,我尚未完全测试此方法。

以下是您的latex模板示例:

\somevalue{((variable))}

最重要的部分是设置variable_start_stringvariable_end_string选项:

>>> import jinja2
>>> env = jinja2.Environment(variable_start_string='((', variable_end_string='))')
>>> t = env.from_string("\somevalue{((variable))}")
>>> t.render(name='Attention!')
'\\somevalue{Attention!}'

Jinja的切换文档概述了(少量)语法差异。来自常见问题解答:

Jinja2的默认语法在许多方面与Django语法相似。但是,这种相似性并不意味着您可以在Jinja2中不经修改地使用Django模板。例如,过滤器参数使用函数调用语法而不是冒号来分隔过滤器名称和参数。此外,Jinja中的扩展接口与Django的基本不同,这意味着您的自定义标签将不再起作用。

Django 1.9和1.8以及其他版本可能已内置对Jinja的支持。

我没有找到配置Django中Jinja语法的示例,目前无法测试,但我认为您需要根据需要更改TEMPLATES['OPTIONS']字典:

    block_start_string='(#',
    block_end_string='#)',
    variable_start_string='((',
    variable_end_string='))',
    comment_start_string='((#',
    comment_end_string='#))',

非常感谢!这个方法解决了我的问题——尽管在配置方面出现了一些问题——生成的 PDF 没有任何不必要的空白。请问您知道是否可以创建一个包含所有变量的字典,并将该字典传递给 jinja 渲染函数(就像 Django 的上下文一样)吗? - kidman01

1
我找到的解决方法是在模板渲染后去除多余的空格:
template = select_template(self.get_template_names())
latex_content = template.render(context)
latex_content = re.sub(r'\{ ', '{', latex_content)
latex_content = re.sub(r' \}', '}', latex_content)

这种方法的好处是不需要在模板中添加额外的模板标签。然而,缺点是需要让模板编写者意识到这种行为,并在使用花括号时考虑它。
实际上,编写一个自定义的模板类来处理这个问题可能会更好。
注意,使用这种方法时,没有理由使用空格作为分隔符,而不是其他任何字符。为了使模板编写者和读者更清楚,可以使用另一个能引起他们注意的字符,例如:

template.tex

\somevalue{§{{ variable }}§}

views.py

template = select_template(self.get_template_names())
latex_content = template.render(context)
latex_content = re.sub(r'\{§', '{', latex_content)
latex_content = re.sub(r'§\}', '}', latex_content)

这表明如果有空格,则意图明确。我认为已经很清楚,§ 在任何地方都不打算显示。

谢谢你的提示。听起来很合理,但不幸的是我无法“访问”渲染的模板。我收到了一个错误,说我不能在二进制对象上使用字符串方法... - kidman01
我猜你会做类似这样的事情:latex_content = template.render(context).encode('utf-8')。在替换后,只需调用.encode('utf-8')即可。 - Antoine Pinsard
你说得对。它运行良好... 我现在实际上更喜欢这种方法,因为我在使用Jinja时遇到了CSRF的问题... 非常感谢! - kidman01

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接