Определить тип переменной в шаблоне 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%}