【问题标题】:Building a list in Django templates在 Django 模板中构建列表
【发布时间】:2011-05-22 16:01:21
【问题描述】:

使用此代码:

{% for o in [1,2,3] %}
    <div class="{% cycle 'row1' 'row2' %}">
        {% cycle 'row1' 'row2' %}
    </div>
{% endfor %}

我收到TemplateSyntaxError

Could not parse the remainder: '[1,2,3]' from '[1,2,3]'

有没有办法在模板中建立一个列表?

【问题讨论】:

  • 你不能在 django 模板中定义一个列表,但你必须提供列表作为你 views.py 的参数
  • @domonic 我的意思是他不能像在普通 python 代码中那样启动一个列表,否则还有其他方法可以在模板中创建列表。但是我找不到使用创建列表并无处使用列表项的理由,最好不要在模板中创建列表并从视图本身定义它们。如果我错了,请纠正我。
  • @dcrodjer 是的,创建列表然后不使用它们显然不是一个好主意。是的,最好从视图中创建它们。

标签: django django-templates


【解决方案1】:

我们可以在 str 对象上使用 split 方法:

page.html:

{% with '1 2 3' as list %}
  {% for i in list.split %}
    {{ i }}<br>
  {% endfor %}
{% endwith %}

结果:

1
2
3

【讨论】:

  • 直接提供'1 2 3'而不使用split方法会起作用。
  • 是的,但我认为您会将空格视为列表的元素。
  • 你是对的,我的用例是在一个测试中,如果 x in "1 2 3",它按预期工作。在 for 循环中,您可以执行 {% for i in "123" %} 这将起作用;)
  • 我在这个主题上看到的最佳答案
【解决方案2】:

您可以通过巧妙地使用make_list 过滤器来做到这一点,但这可能是个坏主意:

{% for o in "123"|make_list %}
    <div class="{% cycle 'row1' 'row2' %}">
        {% cycle 'row1' 'row2' %}
    </div>
{% endfor %}

附言。您似乎没有在任何地方使用o,所以我不确定您要做什么。

【讨论】:

  • @zhm1126 不,你可能不应该在模板中构建dicts。
  • @zjm1126 如果您认为需要在模板中构建 dict,请发布一个包含您要解决的问题的新问题,并在此处添加带有问题链接的评论,我会看看。几乎可以肯定有更好的方法。
【解决方案3】:

我制作了这个模板标签来实现这个目标。

from django import template
register = template.Library()

# use @register.assignment_tag
# only when you're working with django version lower than 1.9
@register.simple_tag
def to_list(*args):
    return args

在模板中使用它:

{% load your_template_tag_file %}
{% to_list 1 2 3 4 5 "yes" as my_list %}
{% for i in my_list %}
    {{ i }}
{% endfor %}

参考这里: Django simple tags

【讨论】:

  • 简洁至上。也像魅力一样工作,并且对于每种类型的数据,不仅是字符串(在 1.9 上使用 simple_tag 进行测试)。我不敢相信这样微不足道的事情,因为这还不是 Django 巨大引擎的一部分!
  • 模板标签文件必须放在网站的templatetags子目录(包)中。
【解决方案4】:

这里的其他答案看起来像一张票(至少对于我想要的),所以我会提供一个答案,说明你为什么想做这样的事情(对于我的情况,也许有比什么更好的答案已提供):

我遇到了这个问题,正在寻找一种使用 Bootstrap 构建 3 个非常相似但不相同的按钮的方法。一个按钮可能看起来像

<div class="btn-group">
  <a class="btn btn-primary dropdown-toggle" data-toggle="dropdown" href="#">
    Modality
    <span class="caret"></span>
  </a>
  <ul class="dropdown-menu" id="Modality">
    <li><a href="#">Action</a></li>
  </ul>
</div>

按钮之间的区别仅限于按钮的文本(Modality,在上面单独的一行)和与按钮相关的内容,我们假设它是由 JS 动态填充的(引用 id="模态”)。

如果我需要制作其中的 10 个,复制/粘贴 HTML 似乎很愚蠢和乏味,特别是如果我想在事后更改按钮的任何内容(比如将它们全部设为拆分下拉菜单)并且它会继续对抗 DRY。

因此,相反,我可以在模板中执行类似

的操作
{% with 'Modality Otherbutton Thirdbutton' as list %}
  {% for i in list.split %}
    <!-- copy/paste above code with Modality replaced by {{ i }} -->
  {% endfor %}
{% endwith %}

现在,授予,在这种特殊情况下,按钮将功能添加到一些相关的数据网格,因此按钮名称也可以从 django 模型来源的数据中动态填充,但我的设计还没有到那个阶段现在,您可以看到需要这种功能来保持 DRY 的位置。

【讨论】:

  • 我出于同样的原因来到这里,只是想减少模板中的重复。 +1 发布一个现实的例子
  • 或者,您可以将重复的代码移出模板,将按钮名称作为变量,然后使用withinclude...
  • 你可以,但如果我没记错的话,这个想法是按钮都在表示层中,与逻辑无关,所以为了制作模板,将额外的变量放入逻辑中工作不是很干净。
【解决方案5】:

最简单的就是做

{% for x in "123" %}

【讨论】:

    【解决方案6】:

    drodger 是正确的,你不能在故意残废的 Django 模板语言中这样做。在调用模板时将列表作为上下文变量传入 尝试使用expr 之类的模板标记。然后你可以说{% expr [1,2,3] as my_list %},然后在你的for循环中使用my_list

    【讨论】:

    • @Dominic:我怀疑他脑子里有一个更笼统的案例,但我不知道它可能是什么。
    【解决方案7】:

    这也许是一个灵感。使用内置过滤器add

    {{ first|add:second }}
    
    first is [1, 2, 3] and second is [4, 5, 6], then the output will be [1, 2, 3, 4, 5, 6].
    
    This filter will first try to coerce both values to integers. 
    If this fails, it'll attempt to add the values together anyway. 
    This will work on some data types (strings, list, etc.) and fail on others. 
    If it fails, the result will be an empty string.
    

    官方规范,https://docs.djangoproject.com/zh-hans/2.0/ref/templates/builtins/#built-in-filter-reference

    【讨论】:

      猜你喜欢
      • 2011-04-12
      • 2011-12-31
      • 2012-12-18
      • 1970-01-01
      • 2019-02-03
      • 2014-06-18
      • 2014-11-16
      • 2019-03-05
      • 1970-01-01
      相关资源
      最近更新 更多