Как мне отформатировать дату в Jinja2?

183

Используя Jinja2, как мне отформатировать поле даты? Я знаю, в Python я могу просто сделать это:

print(car.date_of_manufacture.strftime('%Y-%m-%d'))

Но как мне отформатировать дату в Jinja2?

Ambrosio
источник

Ответы:

327

Есть два способа сделать это. Прямой подход заключается в простом вызове (и распечатке) метода strftime () в вашем шаблоне, например

{{ car.date_of_manufacture.strftime('%Y-%m-%d') }}

Другим, более подходящим подходом было бы определение собственного фильтра, например:

from flask import Flask
import babel

app = Flask(__name__)

@app.template_filter()
def format_datetime(value, format='medium'):
    if format == 'full':
        format="EEEE, d. MMMM y 'at' HH:mm"
    elif format == 'medium':
        format="EE dd.MM.y HH:mm"
    return babel.dates.format_datetime(value, format)

(Этот фильтр основан на babel по причинам, связанным с i18n, но вы также можете использовать strftime). Преимущество фильтра в том, что вы можете написать

{{ car.date_of_manufacture|datetime }}
{{ car.date_of_manufacture|datetime('full') }}

который выглядит лучше и более ремонтопригоден. Другим распространенным фильтром является также фильтр «timedelta», который оценивается как что-то вроде «написано 8 минут назад». Вы можете использовать babel.dates.format_timedeltaдля этого и зарегистрировать его в качестве фильтра, аналогичного приведенному здесь примеру datetime.

tux21b
источник
2
ты на самом деле пробовал это? прямой вызов приводит к следующему: у объекта time.struct_time нет атрибута strftime
Карл П
7
По вашему вопросу вы говорите о чем-то другом. Изначально этот поток был о форматировании datetimeобъекта из модуля python datetime, но вы пытаетесь отформатировать struct_timeобъект из timeмодуля низкого уровня . struct_timeУ объектов нет strftime()метода, хотя strftime()в пакете времени может быть глобальный метод. Но я рекомендую вам использовать datetimeпакет высокого уровня (независимый от платформы) .
tux21b
2
Я думаю, что вы имеете в видуbabel.dates.format_datetime(value, format)
Johnboiles
2
определяя новый фильтр, никак не лучше. Больше кода для записи = больше кода для поддержки = больше кода для анализа, битового кэширования (если используется) и интерпретации. Одним из больших преимуществ использования Jinja2 является возможность написания небольшого кода Python внутри шаблона. От этого зависит некоторое увеличение производительности по сравнению с системой шаблонов Django.
StefanNch
4
@StefanNch "определение нового фильтра ничем не лучше". Это может быть: если фильтр вызывается много раз в шаблонах, это позволяет избежать повторения строки формата и может привести к записи меньшего количества кода. И еще более важный, менее повторяющийся код, добавляя абстракцию.
jacquev6
21

Вот фильтр, который я использовал для strftime в Jinja2 и Flask

@app.template_filter('strftime')
def _jinja2_filter_datetime(date, fmt=None):
    date = dateutil.parser.parse(date)
    native = date.replace(tzinfo=None)
    format='%b %d, %Y'
    return native.strftime(format) 

И тогда вы используете фильтр так:

{{car.date_of_manufacture|strftime}}
Радж
источник
2
Почему dateutilи native?
GWG
16

Я думаю, что вы должны написать свой собственный фильтр для этого. На самом деле это пример пользовательских фильтров в документации: http://jinja.pocoo.org/docs/api/#custom-filters

Брайан Голдман
источник
15

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

Например:

import time
context={
    'now':int(time.time()),
    'strftime':time.strftime }  # Note there are no brackets () after strftime
                                # This means we are passing in a function, 
                                # not the result of a function.

self.response.write(jinja2.render_template('sometemplate.html', **context))

Который затем может быть использован в sometemplate.html:

<html>
    <body>
        <p>The time is {{ strftime('%H:%M%:%S',now) }}, and 5 seconds ago it was {{ strftime('%H:%M%:%S',now-5) }}.
    </body>
</html>
Olly FG
источник
7

Вы можете использовать это в шаблоне без фильтров

{{ car.date_of_manufacture.strftime('%Y-%m-%d') }}
Зайцев Дмитрий
источник
0

в колбе, с бабелом, мне нравится делать это:

@app.template_filter('dt')
def _jinja2_filter_datetime(date, fmt=None):
    if fmt:
        return date.strftime(fmt)
    else:
        return date.strftime(gettext('%%m/%%d/%%Y'))

используется в шаблоне с {{mydatetimeobject|dt}}

так что нет с babel, вы можете указать свой различный формат в messages.po, например, так:

#: app/views.py:36
#, python-format
msgid "%%m/%%d/%%Y"
msgstr "%%d/%%m/%%Y"
euri10
источник