Come posso formattare una data in Jinja2?


183

Utilizzando Jinja2, come posso formattare un campo data? So che in Python posso semplicemente fare questo:

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

Ma come posso formattare la data in Jinja2?

Risposte:


327

Ci sono due modi per farlo. L'approccio diretto sarebbe semplicemente chiamare (e stampare) il metodo strftime () nel modello, ad esempio

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

Un altro approccio visivamente migliore sarebbe quello di definire il proprio filtro, ad esempio:

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)

(Questo filtro si basa su babel per motivi riguardanti i18n, ma puoi usare anche strftime). Il vantaggio del filtro è che puoi scrivere

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

che sembra più bello ed è più mantenibile. Un altro filtro comune è anche il filtro "timedelta", che valuta qualcosa come "scritto 8 minuti fa". Puoi usarlo babel.dates.format_timedeltae registrarlo come filtro simile all'esempio datetime qui fornito.


2
ci hai provato davvero? chiamandolo direttamente si ottiene: 'time.struct_time object' non ha attributo 'strftime'
Karl P

7
Secondo la tua domanda, stai parlando di qualcosa di diverso. Inizialmente, questo thread riguardava la formattazione di un datetimeoggetto dal modulo Python datetime, ma stai provando a formattare un struct_timeoggetto dal timemodulo di basso livello . struct_timegli oggetti non hanno un strftime()metodo, sebbene strftime()nel pacchetto temporale potrebbe esserci un metodo globale . Ti consiglio invece di usare il datetimepacchetto di alto livello (indipendente dalla piattaforma) .
tux21b,

2
Penso che intendibabel.dates.format_datetime(value, format)
johnboiles il

2
la definizione di un nuovo filtro non è in alcun modo migliore. Più codice da scrivere = più codice da mantenere = più codice da analizzare, cache (se utilizzato) e interpretato. Uno dei grandi vantaggi dell'utilizzo di Jinja2 è la capacità di scrivere un piccolo codice Python all'interno del modello. Alcuni dei miglioramenti delle prestazioni, rispetto al sistema di template di Django, derivano da questo.
StefanNch,

4
@StefanNch "la definizione di un nuovo filtro non è in alcun modo migliore". Può essere: se il filtro viene chiamato più volte nei modelli, questo evita di ripetere la stringa di formato e può comportare la scrittura di meno codice. E ancora più importante, codice meno ripetuto , aggiungendo un'astrazione.
jacquev6,

21

Ecco il filtro che ho finito per usare per strftime in Jinja2 e 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) 

E quindi usi il filtro in questo modo:

{{car.date_of_manufacture|strftime}}

2
Perché sono dateutile native?
Gwg


15

Se hai a che fare con un oggetto temporale di livello inferiore (spesso uso solo numeri interi) e non voglio scrivere un filtro personalizzato per qualsiasi motivo, un approccio che uso è quello di passare la funzione strftime nel modello come variabile, dove può essere chiamato dove ne hai bisogno.

Per esempio:

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

Che può quindi essere utilizzato all'interno di 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>

7

Puoi usarlo in questo modo nel modello senza filtri

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


0

in pallone, con babele, mi piace fare questo:

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

utilizzato nel modello con {{mydatetimeobject|dt}}

quindi no con babel puoi specificare i tuoi vari formati in message.po come questo per esempio:

#: app/views.py:36
#, python-format
msgid "%%m/%%d/%%Y"
msgstr "%%d/%%m/%%Y"

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.