Определить тип переменной в шаблоне django

У меня есть переменная, которую я помещаю в таблицу, которая иногда является датой, а иногда строкой. Если переменная является датой, я хочу изменить форматирование:

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

Но если это строка, я просто хочу отобразить ее как есть:

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

Если я пытаюсь отформатировать его, и это строка, я не получаю вывод для переменной.

Как я могу определить тип, чтобы я мог настроить свой рендеринг на основе типа.

6 ответов

Решение

Как указал Игнасио Васкес-Абрамс в первом комментарии, это не очень хороший способ кодировать вашу логику. Я хотел бы убедиться, что ваша переменная имеет определенный тип. Это можно решить с помощью дополнительной переменной, которую вы добавляете в контекст, или объекта, который содержит данные, и чего-то, что описывает тип данных.

Если вы хотите придерживаться своей логики, возможный подход - написать собственный шаблонный фильтр (назовем его date_or_string). Фильтр может наследовать встроенный date Фильтр с параметром формата является необязательным. Если параметр передан, он работает как обычный date фильтр без параметра просто возвращает строку. В более сложном сценарии фильтр также может выполнять некоторую проверку типов. Просто идея, я бы не стал использовать такую ​​логику в шаблоне.

Вы также можете реализовать общий шаблонный фильтр как эквивалент 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 %}

Однако я думаю, что Игнасио и Дирк правы. Разве вы не можете просто иметь два ключа (вы говорите "массив", но я предполагаю, что вы имеете в виду "словарь" из-за того, что элементы имеют имена) date а также detail?

# 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 action.extra_column.year %}
  {{ action.extra_column|date:"M y" }}
{% else %}
  {{ action.extra_column }}
{% endif %}

Можете ли вы возразить, что это определенно неправильный способ? Вероятно. Сможет ли он выполнить свою работу без написания собственного фильтра шаблонов и без необходимости поддерживать еще больше кода? Абсолютно.

Я знаю, что отстаю в этом (на три года), но я просто пришел сюда, чтобы сделать что-то похожее, и придумал, как мне кажется, достойное решение.

Просто добавьте функцию к своим моделям, как 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 %}

Это мой подход:

      @register.filter
def get_type(value):
    """ It returns variable type as a pure string name """
    return type(value).__name__

Вы можете попробовать это, чтобы распознать тип String vs List:

{%if v_1.0.1|length == 0%}
    <!--STR-->
    {{v_1}}
{%else%}     
     <!--List-->                                           
    {{v_1.0}}
{%endif%}
Другие вопросы по тегам