Comment formater une date dans Jinja2?

183

À l'aide de Jinja2, comment mettre en forme un champ de date? Je sais qu'en Python, je peux simplement faire ceci:

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

Mais comment formater la date dans Jinja2?

Ambrosio
la source

Réponses:

327

Il y a deux manières de procéder. L'approche directe serait d'appeler (et d'imprimer) simplement la méthode strftime () dans votre modèle, par exemple

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

Une autre approche légèrement meilleure serait de définir votre propre filtre, par exemple:

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)

(Ce filtre est basé sur babel pour des raisons concernant i18n, mais vous pouvez également utiliser strftime). L'avantage du filtre est que vous pouvez écrire

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

qui a l'air plus joli et est plus facile à entretenir. Un autre filtre commun est également le filtre "timedelta", qui évalue quelque chose comme "écrit il y a 8 minutes". Vous pouvez l'utiliser babel.dates.format_timedeltapour cela et l'enregistrer en tant que filtre similaire à l'exemple datetime donné ici.

tux21b
la source
2
avez-vous réellement essayé cela? l'appeler directement entraîne: 'time.struct_time object' n'a pas d'attribut 'strftime'
Karl P
7
Selon votre question, vous parlez de quelque chose de différent. Initialement, ce fil concernait le formatage d'un datetimeobjet à partir du module python datetime, mais vous essayez de formater un struct_timeobjet à partir du timemodule de bas niveau . struct_timeles objets n'ont pas de strftime()méthode, bien qu'il puisse y avoir une strftime()méthode globale dans le package de temps. Mais je vous recommande d'utiliser le datetimepackage de haut niveau (indépendant de la plate-forme) à la place.
tux21b
2
Je pense que tu veux direbabel.dates.format_datetime(value, format)
johnboiles
2
définir un nouveau filtre, n'est en aucun cas mieux. Plus de code à écrire = plus de code à maintenir = plus de code à analyser, mis en cache binaire (si utilisé) et interprété. L'un des grands avantages de l'utilisation de Jinja2 est la possibilité d'écrire du petit code Python à l'intérieur du modèle. Certains des gains de performances, par rapport au système de template de Django, viennent de cela.
StefanNch
4
@StefanNch "définir un nouveau filtre, ce n'est en aucun cas mieux". Cela peut être: si le filtre est appelé plusieurs fois dans les modèles, cela évite de répéter la chaîne de format et peut entraîner moins d'écriture de code. Et encore plus important, du code moins répété , en ajoutant une abstration.
jacquev6
21

Voici le filtre que j'ai fini par utiliser pour strftime dans Jinja2 et 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) 

Et puis vous utilisez le filtre comme ceci:

{{car.date_of_manufacture|strftime}}
Raj
la source
2
Pourquoi dateutilet native?
gwg
15

Si vous avez affaire à un objet de temps de niveau inférieur (j'utilise souvent simplement des entiers) et que vous ne voulez pas écrire de filtre personnalisé pour une raison quelconque, une approche que j'utilise consiste à passer la fonction strftime dans le modèle en tant que variable, où il peut être appelé là où vous en avez besoin.

Par exemple:

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

Qui peut ensuite être utilisé dans 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
la source
7

Vous pouvez l'utiliser comme ça dans un modèle sans aucun filtre

{{ car.date_of_manufacture.strftime('%Y-%m-%d') }}
Zaytsev Dmitry
la source
0

en flacon, avec babel, j'aime faire ça:

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

utilisé dans le modèle avec {{mydatetimeobject|dt}}

donc non avec babel vous pouvez spécifier vos différents formats dans messages.po comme ceci par exemple:

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