【问题标题】:Determine variable type within django template确定 django 模板中的变量类型
【发布时间】:2012-08-14 22:11:19
【问题描述】:

我有一个变量,我将它放入一个有时是日期,有时是字符串的表中。如果变量是日期,我想更改格式:

<td>{{ action.extra_column|date:"M d" }}</td>

但如果是字符串,我只想按原样显示:

<td>{{ action.extra_column }}</td>

如果我尝试格式化它并且它是一个字符串,我不会得到变量的输出。

如何确定类型,以便根据类型调整渲染。

【问题讨论】:

  • 这取决于正在传递的变量。老实说,这有点简化。 views.py 传递了一个包含变量“extra_column”的数组。将此视为“动作”的一个特征。根据模板的上下文,我想显示操作的日期,或者我可能想显示操作的详细信息。所以它总是action.extra_column,但是这个extra_column可能是一个日期,也可能是一个字符串。
  • 我认为您需要在问题中包含更多代码,例如定义action 的视图中的行。听起来您正试图在模板中放入太多逻辑。一般来说,只需确保您的视图将正确的数据传递给您的模板,您不需要做太多工作来确保它以 HTML 格式正确显示。

标签: django django-templates


【解决方案1】:

您还可以实现一个通用模板过滤器,以等效于 type() 内置:

# app/templatetags/util.py
from django import template

register = template.Library()

@register.filter
def get_type(value):
    return type(value)

# template.html
{% load util %}
{% if extra_column|get_type == 'str' %}
    String
{% elif extra_column|get_type == 'datetime.date' %}
    Date
{% else %}
    Oh no!
{% endif %}

不过,我认为 Ignacio 和 Dirk 是对的。难道你不能只有两个键(你说“数组”,但我假设你的意思是“字典”,因为项目有名称)称为datedetail

# views.py
...
actions = [{
    'some_property': 'some_value'
    'date': None,
    'detail': 'details'
},
{
    'some_property': 'some_value'
    'date': datetime.date.today(),
    'detail': None
}]
...

# template.html
{% for action in actions %}
<td>{% if action.date %}{{ action.date|date:"M d" }}{% endif %}{{ action.detail }}</td>
{% endfor %}

# output
<td>details</td>
<td>Aug 19</td>

【讨论】:

  • 我认为这更多是因为我没有足够彻底地解释这个例子。数据以您建议的方式定义,但模板需要知道是显示日期还是显示详细信息。即使这样,它也需要知道要显示哪个日期或哪个详细信息(有几个不同的日期字段和几个不同的详细信息字段)。此选择取决于视图的类别。我可以写一个很长的 if 语句,但我选择通过字典传递正确的字段。
  • 我的意思是模板不需要知道是显示日期还是显示细节;它肯定可以只显示定义的任何一个吗?
  • 是的。但很多时候,它们都是被定义的。但即使它们不是,选择也取决于视图的上下文。对不起,我解释得不够清楚。
  • 我知道建议getattribute 过滤器很快就会回来咬我...我认为尝试在同一个模板中使用两者是一个 GIANT RED FLAG您试图在模板层中放置太多逻辑。只是我的$.02
  • 感谢您的回答。尽管如此,我将返回值更改为type(value).__name__,否则get_type 为浮点返回"&lt;class 'float'&gt;" 而不是"float",因此比较{% if number|get_type == 'float' %} 总是会触发else-part...
【解决方案2】:

就像 Ignacio Vazquez-Abrams 在第一条评论中指出的那样,这并不是编写逻辑代码的好方法。我会确保您的变量具有某种类型。这可以通过添加到上下文的附加变量或保存数据的对象以及描述数据类型的内容来解决。

如果您想坚持自己的逻辑,一种可能的方法是编写自己的模板过滤器(我们称之为date_or_string)。过滤器可以继承内置的date 过滤器,格式参数是可选的。如果参数被传递,它就像普通的date 过滤器一样工作,没有参数它只是返回字符串。在更复杂的情况下,过滤器还可以进行一些类型检查。只是一个想法,我实际上不会将这种逻辑放入模板中。

【讨论】:

    【解决方案3】:

    我知道我在这方面落后了很多(三年),但我刚到这里是为了做类似的事情,并想出了我认为不错的解决方案。

    只需向您的模型添加一个函数,例如 get_model_type,并让它返回您对每个模型的期望,如下所示:

    class MyModelOne(models.Model):
      date_created = models.DateTimeField(auto_now_add=True)
      first_name = models.CharField(max_length=255)
      def get_model_type(self):
        return "my_model_one"
    
    class MyModelTwo(models.Model):
      date_created = models.DateTimeField(auto_now_add=True)
      other_field = models.CharField(max_length=255)
      def get_model_type(self):
        return "my_model_two"
    

    然后在您的模板中,您可以轻松地调用该函数:

    {% if model.get_model_type == 'my_model_one' %}
      <p>Model One</p>
    {% elif model.get_model_type == 'my_model_two' %}
      <p>Model Two</p>
    {% endif %}
    

    【讨论】:

      【解决方案4】:

      聚会迟到了,但我遇到了这个问题。我寻求的解决方案是duck-typing,所以:

      {% if action.extra_column.year %}
        {{ action.extra_column|date:"M y" }}
      {% else %}
        {{ action.extra_column }}
      {% endif %}
      

      您能说这绝对不是正确的做法吗?大概。它会在不编写自己的模板过滤器并且需要维护更多代码的情况下完成工作吗?绝对的。

      【讨论】:

        【解决方案5】:

        你可以试试这个来识别 String 和 List 类型:

        {%if v_1.0.1|length == 0%}
            <!--STR-->
            {{v_1}}
        {%else%}     
             <!--List-->                                           
            {{v_1.0}}
        {%endif%}
        

        【讨论】:

          猜你喜欢
          • 2012-09-12
          • 2011-01-14
          • 1970-01-01
          • 2021-01-18
          • 1970-01-01
          • 2017-09-14
          • 2020-12-04
          • 1970-01-01
          • 2015-09-20
          相关资源
          最近更新 更多