2013-10-24T06:49:48Z
Flask-Moment: Flask and Jinja2 Integration with moment.js
If you followed my Mega-Tutorial articles you may remember that I dedicated an entire article to the topic of rendering dates and times.
I needed to revisit this problem for my upcoming book, and this time I decided to package this functionality in an extension. That is how Flask-Moment was born.
Installation
As usual, you can install this extension with pip:
$ pip install flask-moment
Initialization and Configuration
Class Moment must be created to initialize the extension:
from flask import Flask
from flask.ext.moment import Moment
app = Flask(__name__)
moment = Moment(app)
The delayed initialization style with init_app() is also supported.
After that you have to include jquery.js and moment.js in your template(s). The template now has helper functions to make this easy:
<html>
<head>
<title>Flask-Moment example app</title>
{{ moment.include_jquery() }}
{{ moment.include_moment() }}
</head>
<body>
...
</body>
</html>
Note that you can include the scripts at the bottom of the page as well.
Both javascript files are imported from a CDN. If you want to use a specific version of these files you can pass the full version number as a string argument into each function. If you already have jquery included in your page then you can omit the include_jquery() line, but note that the include_moment() line must be present.
If you work in a language that is not English, then you can also set the language in the <head> section:
{{ moment.lang("es") }}
Usage
The usage in Jinja2 templates tries to mimic the style of the original APIs in Javascript.
For example, this will render the current time with a custom format string:
<p>The current date and time is: {{ moment().format('MMMM Do YYYY, h:mm:ss a') }}.</p>
If you want to render an instance of datetime instead of the current time then pass it as an argument to the moment() constructor:
<p>The current date and time is: {{ moment(timestamp).format('MMMM Do YYYY, h:mm:ss a') }}.</p>
Note that the timestamp argument must be a "naive" datetime instance expressed in UTC (see the datetime documentation for a discussion on naive date and time objects).
The rendered time will always be in the client's local time.
These are the render styles that are supported:
format(format_string): custom format.fromNow(no_suffix = False): relative to current time (i.e. "N minutes ago", "in N hours", etc.).fromTime(another_timesatmp, no_suffix = False): relative to the given timestamp.calendar(): another format relative to current time ('last Monday 3PM", "Tomorrow 1:30AM", etc.).valueOf(): number of milliseconds since Unix Epoch.unix(): number of seconds since Unix Epoch.
The rendered dates and times can be refreshed periodically by passing a refresh = True argument to any of the above functions. This is useful for the relative formats, because they are updated as time passes. The refresh interval is fixed at one minute.
Conclusion
I hope you find this little extension useful. The source code is available on github, and a demo application is included.
If you have any ideas for improvements let me know below in the comments.
Miguel


#1 Collin said 2013-10-24T13:11:42Z
#2 dowlf said 2013-10-26T13:58:21Z
#3 Sam said 2013-11-22T12:10:04Z
#4 Miguel Grinberg said 2013-11-22T15:11:08Z
#5 Nedda Kaltcheva said 2014-12-22T12:42:31Z
#6 Bruce said 2015-07-13T12:13:44Z
#7 Miguel Grinberg said 2015-07-16T06:03:03Z
#8 Nou said 2015-07-22T11:58:41Z
#9 Miguel Grinberg said 2015-07-22T18:21:22Z
#10 Ryan said 2016-01-15T02:22:54Z
#11 Miguel Grinberg said 2016-01-16T23:06:25Z
#12 Andrey said 2016-02-22T05:44:00Z
#13 Miguel Grinberg said 2016-02-24T18:09:18Z
#14 Brian Wilson said 2016-04-10T18:59:43Z
#15 Miguel Grinberg said 2016-04-20T14:57:39Z
#16 transreductionist said 2016-05-28T17:53:58Z
#17 transreductionist said 2016-05-28T22:29:08Z
#18 ujang said 2016-07-02T13:56:04Z
#19 Miguel Grinberg said 2016-07-14T18:47:55Z
#20 Andrey Glazkov said 2020-05-22T22:23:35Z
#21 Miguel Grinberg said 2020-05-23T09:54:08Z