如何在不在输出中保留格式化空格的情况下格式化Django模板?

huangapple go评论41阅读模式
英文:

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

huangapple
  • 本文由 发表于 2023年5月17日 18:25:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/76271090.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定