Jak sformatować datę w Jinja2?

183

Jak sformatować pole daty w Jinja2? Wiem, że w Pythonie mogę po prostu to zrobić:

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

Ale jak sformatować datę w Jinja2?

Ambrosio
źródło

Odpowiedzi:

327

Można to zrobić na dwa sposoby. Bezpośrednim podejściem byłoby na przykład wywołanie (i wydrukowanie) metody strftime () w szablonie

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

Innym, widocznie lepszym rozwiązaniem byłoby zdefiniowanie własnego filtra, np .:

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)

(Ten filtr jest oparty na Babel z powodów związanych z i18n, ale możesz także użyć strftime). Zaletą filtra jest to, że możesz pisać

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

który wygląda ładniej i jest łatwiejszy w utrzymaniu. Innym powszechnym filtrem jest również filtr „timedelta”, który daje wynik podobny do „napisanego 8 minut temu”. Możesz babel.dates.format_timedeltado tego użyć i zarejestrować go jako filtr podobny do podanego tutaj przykładu datetime.

tux21b
źródło
2
czy rzeczywiście tego próbowałeś? wywołanie go bezpośrednio powoduje: „time.struct_time object” nie ma atrybutu „strftime”
Karl P
7
Zgodnie z twoim pytaniem mówisz o czymś innym. Początkowo ten wątek dotyczył formatowania datetimeobiektu z modułu python datetime, ale próbujesz sformatować struct_timeobiekt z modułu niskiego poziomu time. struct_timeobiekty nie mają strftime()metody, chociaż strftime()w pakiecie czasu może znajdować się metoda globalna . Ale zalecam użycie datetimezamiast tego pakietu wysokiego poziomu (niezależnego od platformy) .
tux21b
2
Myślę, że masz na myślibabel.dates.format_datetime(value, format)
johnboiles
2
zdefiniowanie nowego filtra nie jest w żaden sposób lepsze. Więcej kodu do napisania = więcej kodu do utrzymania = więcej kodu do przeanalizowania, buforowania bitów (jeśli jest używany) i interpretacji. Jedną z dużych zalet używania Jinja2 jest możliwość pisania małego kodu python wewnątrz szablonu. Wynika to z pewnego wzrostu wydajności w porównaniu z systemem szablonów Django.
StefanNch,
4
@StefanNch „zdefiniowanie nowego filtra nie jest w żaden sposób lepsze”. Może to być: jeśli filtr jest wywoływany wiele razy w szablonach, pozwala to uniknąć powtarzania ciągu formatu i może skutkować zapisaniem mniejszej ilości kodu. I jeszcze ważniejszy, mniej powtarzany kod, dodając abstrację.
jacquev6,
21

Oto filtr, którego użyłem do strftime w Jinja2 i 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) 

A potem używasz filtra tak:

{{car.date_of_manufacture|strftime}}
Raj
źródło
2
Dlaczego dateutili native?
gwg
15

Jeśli masz do czynienia z obiektem czasowym niższego poziomu (często używam po prostu liczb całkowitych) i nie chcesz pisać niestandardowego filtra z jakiegokolwiek powodu, stosuję podejście polegające na przekazaniu funkcji strftime do szablonu jako zmiennej, gdzie można go nazwać tam, gdzie go potrzebujesz.

Na przykład:

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))

Które następnie można wykorzystać w 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
źródło
7

Możesz użyć tego w szablonie bez filtrów

{{ car.date_of_manufacture.strftime('%Y-%m-%d') }}
Zajcew Dmitrij
źródło
0

w kolbie z babelem lubię to robić:

@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'))

używane w szablonie z {{mydatetimeobject|dt}}

więc nie, w Babel możesz określić swój różnorodny format w messages.po, na przykład:

#: app/views.py:36
#, python-format
msgid "%%m/%%d/%%Y"
msgstr "%%d/%%m/%%Y"
euri10
źródło