英文:
How to format Django templates without having formatting white-space in the output?
问题
我需要生成一些txt文件,而Django模板中使用的Jinja2使得模板代码看起来非常混乱,因为我不能使用换行符而不在生成的结果中包含它们。{% spaceless %}
标签可能会使事情变得更混乱,因为很难插入所需的空格。
一个例子:
[{% if foo.condition %}x{% else %} {% endif %}] 已满足的要求列表:{{ foo.requirements_fullfilled }} of {{ foo.num_requirements }} {% for requirement in foo.requirement %}
- {{ requirement.number }}{% if requirement.name %}: {{ solution.exercise.name }}{% endif %}{% endfor %}
请注意在-
之前的换行符,它使得列表在每个项目之前添加一个换行符,以及所有其他标签缺少的换行符,因为它们会在输出中可见。
使用spaceless
可以允许格式化,但也会移除项目符号前的换行符。没有spaceless
,这行看起来相当混乱。我还尝试使用{# #}
和带有换行符的注释作为解决方法,但多行注释需要使用{% comment %}
模板标签,它本身具有相当冗长的名称,例如:
[{% if foo.condition %}{% comment %}
{% endcomment %}x{% comment %}
{% endcomment %}{% else %}{% comment %}
{% endcomment %} {% comment %}{# 注意:这里有一个空格字符在注释标签之间! #}
{% endcomment %}{% endif %}]
这只是生成一个空格或x
的部分。当然,我可以在这里编写一个“如果为真则为x”的过滤器,但这对于其他长行的部分没有帮助。
英文:
I need to generate some txt files and Jinja2 used for Django templates causes the template code to look really messy, because I cannot use line-breaks without having them in the generated result. The {% spaceless %}
tags would probably make things only messier as it will be hard to insert the wanted space.
An example:
[{% if foo.condition %}x{% else %} {% endif %}] List of requirements fulfilled: {{ foo.requirements_fullfilled }} of {{ foo.num_requirements }} {% for requirement in foo.requirement %}
- {{ requirement.number }}{% if requirement.name %}: {{ solution.exercise.name }}{% endif %}{% endfor %}
Note the linebreak before -
which makes the list add a linebreak before each bullet point and the missing linebreaks for all other tags, as they would be visible in the output.
Using spaceless would allow for formatting, but also remove the linebreak before the bullet points. Without spaceless the line looks quite messy. I also tried to use {# #}
with a linebreak inside the comment as workaround, but multi-line comments need to use the {% comment %}
template tag, which itself has a quite verbose name and would result in, for example:
[{% if foo.condition %}{% comment %}
{% endcomment %}x{% comment %}
{% endcomment %}{% else %}{% comment %}
{% endcomment %} {% comment %}{# Attention: Here is a space character between the comment tags! #}
{% endcomment %}{% endif %}]
And that's just the part for generating a space or an x
. Of course, I could write here an "x if true" filter, but this would not help with the rest of the long line.
答案1
得分: 1
将逻辑从模板移到Python视图中。使用基于类的视图,你可以这样做:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['foocon'] = "x" if foo.condition else ""
req_texts = []
for requirement in foo.requirement:
name = f": {solution.exercise.name}" if requirement.name else ""
req_texts.append(f"- {requirement.number}{name}")
context['req_text'] = '\n'.join(req_texts)
return context
然后模板变成:
[{{foocon}}] 已满足要求的列表: {{ foo.requirements_fullfilled }} of {{ foo.num_requirements }}
{{req_text}}
或者你可以在Python中多做一些工作,完全不在模板中使用逻辑,根据模板和要求的其余部分,你可以选择放弃渲染,而是构建一个文本行的Python字符串列表,然后将其作为文本响应返回:
filename = "some-filename.txt"
response = HttpResponse(
'\n'.join(list_of_lines),
content_type='text/plain'
)
response['Content-Disposition'] = f'attachment; filename={filename}'
return response
希望这有帮助!
英文:
Move the logic out of the template into the Python view. Using Class-based views, you could do
def get_context_data( self, **kwargs):
context = super().get_context_data( **kwargs)
context['foocon'] = "x" if foo.condition else " "
req_texts = []
for requirement in foo.requirement:
name = f": {solution.exercise.name}" if requirement.name else ""
req_texts.append(
f"- {requirement.number}{name}" )
context['req_text'] = '\n'.join(req_texts)
return context
And then the template becomes
[{{foocon}}] List of requirements fulfilled: {{ foo.requirements_fullfilled }} of {{ foo.num_requirements }}
{{req_text}}
Or you could do a bit more work in Python and simply substitute one variable with no logic in the template at all.
Depending on the rest of the template and requirements I might dispense with rendering entirely and simply build up a set of text lines as a Python list of strings, then return it as a text response
filename = "some-filename.txt"
response = HttpResponse(
'\n'.join( list_of_lines),
content_type='text/plain'
)
response['Content-Disposition'] = f'attachment; filename={filename}'
return response
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论