Formatting of dates and times in Flask templates using moment.js.

Overview

Flask-Moment

Build Status

This extension enhances Jinja2 templates with formatting of dates and times using moment.js.

Quick Start

Step 1: Initialize the extension:

from flask_moment import Moment
moment = Moment(app)

Step 2: In your <head> section of your base template add the following code:

<head>
    {{ moment.include_jquery() }}
    {{ moment.include_moment() }}
</head>

This extension also supports the Flask application factory pattern by allowing you to create a Moment object and then separately initialize it for an app:

    moment = Moment()

    def create_app(config):
        app = Flask(__name__)
        app.config.from_object(config)
        # initialize moment on the app within create_app()
        moment.init_app(app)

    app = create_app(prod_config)

Note that jQuery is required. If you are already including it on your own then you can remove the include_jquery() line. Secure HTTP is always used to request the external js files..

The include_jquery() and include_moment() methods take some optional arguments. If you pass a version argument to any of these two calls, then the requested version will be loaded from the default CDN. If you pass local_js, then the given local path will be used to load the library. The include_moment() argument takes a third argument no_js that when set to True will assume that the Moment JavaScript library is already loaded and will only add the JavaScript code that supports this extension.

Step 3: Render timestamps in your template. For example:

<p>The current date and time is: {{ moment().format('MMMM Do YYYY, h:mm:ss a') }}.</p>
<p>Something happened {{ moment(then).fromTime(now) }}.</p>
<p>{{ moment(then).calendar() }}.</p>

In the second and third examples template variables then and now are used. These must be instances of Python's datetime class, and must be "naive" objects. See the documentation for a discussion of naive date and time objects. As an example, now can be set as follows:

now = datetime.utcnow()

By default the timestamps will be converted from UTC to the local time in each client's machine before rendering. To disable the conversion to local time pass local=True.

Note that even though the timestamps are provided in UTC the rendered dates and times will be in the local time of the client computer, so each users will always see their local time regardless of where they are located.

Function Reference

The supported list of display functions is shown below:

  • moment(timestamp=None, local=False).format(format_string=None)
  • moment(timestamp=None, local=False).fromNow(no_suffix=False)
  • moment(timestamp=None, local=False).fromTime(another_timesatmp, no_suffix=False)
  • moment(timestamp=None, local=False).toNow(no_suffix=False)
  • moment(timestamp=None, local=False).toTime(another_timesatmp, no_suffix=False)
  • moment(timestamp=None, local=False).calendar()
  • moment(timestamp=None, local=False).valueOf()
  • moment(timestamp=None, local=False).unix()

Consult the moment.js documentation for details on these functions.

Auto-Refresh

All the display functions take an optional refresh argument that when set to True will re-render timestamps every minute. This can be useful for relative time formats such as the one returned by the fromNow() or fromTime() functions. By default refreshing is disabled.

Default Format

The format() function can be invoked without arguments, in which case a default format of ISO8601 defined by the moment.js library is used. If you want to set a different default, you can set the MOMENT_DEFAULT_FORMAT variable in the Flask configuration. Consult the moment.js format documentation for a list of accepted tokens.

Internationalization

By default dates and times are rendered in English. To change to a different language add the following line in the <head> section after the include_moment() line:

{{ moment.locale("es") }}

The above example sets the language to Spanish. Moment.js supports a large number of languages, consult the documentation for the list of languages and their two letter codes.

The extension also supports auto-detection of the client's browser language:

{{ moment.locale(auto_detect=True) }}

Custom locales can also be included as a dictionary:

{{ moment.locale(customizations={ ... }) }}

See the Moment.js locale customizations documentation for details on how to define a custom locale.

Ajax Support

It is also possible to create Flask-Moment timestamps in Python code, for cases where a template is not used. This is the syntax:

timestamp = moment.create(datetime.utcnow()).calendar()

The moment variable is the Moment instance that was created at initialization time.

A timestamp created in this way is an HTML string that can be returned as part of a response. For example, here is how a timestamp can be returned in a JSON object:

return jsonify({ 'timestamp': moment.create(datetime.utcnow()).format('L') })

The Ajax callback in the browser needs to call flask_moment_render_all() each time an element containing a timestamp is added to the DOM. The included application demonstrates how this is done.

Subresource Integrity(SRI)

SRI is a security feature that enables browsers to verify that resources they fetch are not maliciously manipulated. To do so a cryptographic hash is provided that proves integrity.

SRI is enabled by default. If you wish to use another version or want to host your own javascript, a separate hash can be provided. Just add sri=<YOUR-HASH> when calling either moment.include_moment() or moment.include_jquery(). If no sri hash is provided and you choose to use a non default version of javascript, no sri hash will be added.

You can always choose to disable sri. To do so just set sri=False.

Development

Currently the tests are written using pytest.

pip install pytest

To run the tests from the root directory use: py.test.

Reports on coverage with missing line numbers can be generated using pytest-cov:

pip install pytest-cov

And then running: py-test --cov-report term-missing --cov=flask_moment

Comments
  • Add basic docs with Sphinx and Flask-Sphinx-Themes

    Add basic docs with Sphinx and Flask-Sphinx-Themes

    Hey, Miguel. This is a start for adding in docs and addressing #22. I have not worked with Sphinx very much, so any advice you can give me about how to best document this project will be appreciated, and I'll gladly make changes. For example I am not sure how to use these :code:, :class:, or :func: tags and I am also not sure how to use "autodoc". I'm thinking those tags and autodoc probably are work together somehow.

    I used the sphinx-quickstart and based the remaining configuration off of how Flask-Misaka did their docs. As you'll see all I've done is copy the readme into index.rst.

    I figure at this point I should try to get some feedback before going forward. In meantime, I'll look some more into Sphinx.

    Oh, and building the docs should work with:

    pip install sphinx
    pip install Flask-Sphinx-Themes
    make html
    
    question auto-closed 
    opened by wgwz 18
  • Problem using Flask-Moment in IE11 and Edge

    Problem using Flask-Moment in IE11 and Edge

    Hi -

    I'm learning Python Flask and I've built my first simple website. In one of the HTML templates I've included the line: <p>The current date and time is: {{ moment().format('MMMM Do YYYY, h:mm:ss a') }}.</p>

    My init.py file contains the lines: from flask_moment import Moment

    moment = Moment(app)

    My base.html file contains: {% block scripts %} {{ super() }} {{ moment.include_moment() }} {{ moment.locale(auto_detect=True) }} {% endblock %}

    This works fine in Firefox and Chrome, but returns no datetime information in IE11 or Edge.

    I'm running the Flask app on localhost:5000.

    I've attached screenshots from the four browsers to illustrate the problem.

    I'm running MS Windows 10 Home (64-bit) on a Lenovo ThinkPad laptop with Python 3.8.2 (32-bit) and Flask 1.1.2. I'm using Flask_Bootstrap4 4.0.2.

    Apologies if this isn't the right place to raise this question, but I've searched extensively online (stackoverflow, etc) and I haven't been able to find any information that has helped me to resolve it.

    Please let me know if you need any further information.

    Many thanks

    Firefox Firefox Chrome Chrome IE11 IE11 Edge Edge

    question 
    opened by evilocku 14
  • CSP

    CSP

    I added Talisman to my Flask project and tried to properly configure TALISMAN_SECURITY_POLICY but I can't figure out how to get Moment scripts accepted.

    I got the following message(s): Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' 'unsafe-inline' cdnjs.cloudflare.com maxcdn.bootstrapcdn.com code.jquery.com 'nonce-gOu5h3Vkvkid_uTOnxjYsw'". Note that 'unsafe-inline' is ignored if either a hash or nonce value is present in the source list.

    I tried to investigate things a bit further and it looks like it comes from moment.include_jquery() and moment.include_moment(). I wonder if someone (@miguelgrinberg ?) could add an option to include a SHA or a nonce to the script tag (if that's the proper way to do it) or let me know how to circumvent the issue(s).

    question 
    opened by cdruet 14
  • Allow users to optionally supply a CSP nonce to generated inline script

    Allow users to optionally supply a CSP nonce to generated inline script

    If the user has set up a CSP like:

    Content-Security-Policy:
      script-src 'nonce-{random}'
      script-src-elem 'nonce-{random}'
    

    The random is substituted with the provided nonce.

    It is recommended that the user use an extension like Flask-Talisman and set it up as:

    talisman = Talisman()
    
    CSP = {
        # your preferred CSP goes here
    }
    
    talisman.init_app(
        app,
        csp=CSP,
        content_security_policy_nonce_in=["script-src-elem"],
        # ...
    )
    

    and then load Flask-Moment like:

    {% block scripts %}
    {# ... #}
    {{ moment.include_moment(csp_nonce=csp_nonce()) }}
    {# ... #}
    {% endblock %}
    

    Valuable resources:

    question 
    opened by arunanshub 13
  • Safari (13.0.2) doesn't seem to like sri=True

    Safari (13.0.2) doesn't seem to like sri=True

    I'm not sure whether this is properly an error in flask-moment. Apologies if this is the wrong place.

    Using an extremely simple app, I can't seem to get dates to display properly in Safari (13.0.2) with flask-moment (0.9.0) unless I set sri to False in include_moment(). Otherwise, moment.js fails to load and no dates display. In the JavaScript console I see errors related to Access-Control-Allow-Origin, but setting that header manually doesn't have any impact.

    The errors I see:

    [Error] Cross-origin redirection to http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js denied by Cross-Origin Resource Sharing policy: Origin http://localhost:5000 is not allowed by Access-Control-Allow-Origin.
    [Error] Failed to load resource: Cross-origin redirection to http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js denied by Cross-Origin Resource Sharing policy: Origin http://localhost:5000 is not allowed by Access-Control-Allow-Origin. (moment-with-locales.min.js, line 0)
    [Error] Cross-origin script load denied by Cross-Origin Resource Sharing policy.
    [Error] ReferenceError: Can't find variable: moment
    Global Code (localhost:15)
    [Error] Cross-origin script load denied by Cross-Origin Resource Sharing policy.
    [Error] ReferenceError: Can't find variable: moment
    Global Code (localhost:49)
    

    The code I used:

    main.py:

    from flask_bootstrap import Bootstrap
    from flask_moment import Moment
    from flask import Flask, render_template, make_response
    from datetime import datetime
    
    app = Flask(__name__)
    bootstrap = Bootstrap(app)
    moment = Moment(app)
    
    @app.route("/")
    def index():
        return render_template('index.html', current_time=datetime.utcnow())
    
    if __name__ == '__main__':
        app.run()
    

    base.html:

    {% extends "bootstrap/base.html" %}
    {% block head %}
    {{ super() }}
      {% block scripts %}
      {{ super() }}
      {{ moment.include_moment() }}
      {% endblock %}
    {% endblock %}
    
    {% block content %}
      {% block page_content %}
      {% endblock %}
    {% endblock %}
    

    index.html:

    {% extends 'base.html' %}
    
    {% block page_content %}
    Current time: {{ moment(current_time).format('LLL') }}.
    {% endblock %}
    
    investigate 
    opened by cunningjames 7
  • Adds live option + custom refresh

    Adds live option + custom refresh

    • Changes in this commit allow for the use of a 'live' timestamp. See the example file for a live demo.
    • Prevents starting multiple timers for a single object
    • Refresh now allows for other values (like every second).
    • Adds a toNow function
    • All changes are backwards compatible.
    enhancement 
    opened by javl 7
  • Remove use of JavaScript eval() (Closes #60)

    Remove use of JavaScript eval() (Closes #60)

    Pull request of the change proposed here, allowing to remove the use of the eval() JavaScript function. Would also fix #43 and allow to work with a Content-Security-Policy (CSP) that doesn't require unsafe-eval for any JavaScript page on the entire webpage (since that doesn't apply just to the bits from Flask-Moment)

    bug 
    opened by e2jk 6
  • add methods for moment.js subtract, add, diff

    add methods for moment.js subtract, add, diff

    Had trouble with adding .format() to the end of subtract, and add because of render statements being parsed in-between. For this reason these methods expect a format parameter which will be added to the aforementioned moment.js render call.

    Issue #35

    enhancement 
    opened by antmurph 6
  • Setting a default format

    Setting a default format

    I found in using this in my app I use the same string format in all my web pages. When adding new dates in new pages I would have a hard time remembering what exactly that format was. This solves that problem by setting a config variable to the format needed without needing to register a new jinja variable.

    enhancement 
    opened by jacobthetechy 6
  • Eliminate eval, convert to vanilla js

    Eliminate eval, convert to vanilla js

    So for this conversion (regarding eval) I discovered that it was mostly a lot easier than I expected (after initially believing it would be a lot harder than I expected).

    The primary problem presented in this case is regarding the parameters called to the moment. This is why the fromNow exists.

    I thought just a minute ago about how it would be possible to, instead of rendering each parameter as a dataset attribute, simply render a csv string of the parameters and then split on the commas. This becomes more complicated as we start dealing with datatypes (string vs bool vs int, etc.) but I think I could manage it.

    The one point at which I don't think I could manage it anymore is with regard to from as we need to create a new moment.

    It would theoretically be possible to write a getArgs() function that took a type-annotated csv string, e.g. moment:<timestamp>,int:<int> which would then parse those into the correct datatypes. Heck, I could just use JSON I would think, but at that point we're really writing a parser.

    Wow I just noticed I still have a console logger there and a random return. Sorry will clean immediately.

    As regards elimination of JQuery, I think this did it.

    Opinions?

    opened by mas-4 6
  • How to customize fromNow output ?

    How to customize fromNow output ?

    I am displaying time data was received using flask Moment.fromNow. Typically it outputs 'a few seconds ago' but sometimes the sender's clock is a little off and it displays ' in a few seconds' - which makes no sense to the user. To fix this I want to change ' in a few seconds' to 'current' but this does not seem easy using Moment customization so I thought I could simply change the output in jinja2 but cannot see how to capture the output string to change it: Code: {% set moment_text = moment(value.lastupdated).fromNow(no_suffix = False) %}

        {% if moment_text == "in a few seconds"  %}
            {% set moment_text = "current" %}
        {% endif %}
    

    This never fires because moment_text is still a date and not a string. How can I get the output string of Flask Moment so I can test it and change it? Thanks Bill

    enhancement 
    opened by MrBillium 6
  • I keep getting errors trying to format a duration

    I keep getting errors trying to format a duration

    I'd like to format a number of seconds e.g. 150 seconds -> 00:02:30 using Flask-Moment

    I think this should work:

    {{ moment().startOf('day').seconds(s).format('H:mm:ss'); }}
    

    but I get an error jinja2.exceptions.UndefinedError: 'flask_moment._moment object' has no attribute 'startOf'

    question 
    opened by alxcnwy 1
Owner
Miguel Grinberg
Miguel Grinberg
Flask-vs-FastAPI - Understanding Flask vs FastAPI Web Framework. A comparison of two different RestAPI frameworks.

Flask-vs-FastAPI Understanding Flask vs FastAPI Web Framework. A comparison of two different RestAPI frameworks. IntroductionIn Flask is a popular mic

Mithlesh Navlakhe 1 Jan 1, 2022
Restful Api developed with Flask using Prometheus and Grafana for monitoring and containerization with Docker :rocket:

Hephaestus ?? In Greek mythology, Hephaestus was either the son of Zeus and Hera or he was Hera's parthenogenous child. ... As a smithing god, Hephaes

Yasser Tahiri 16 Oct 7, 2022
Beyonic API Python official client library simplified examples using Flask, Django and Fast API.

Beyonic API Python Examples. The beyonic APIs Doc Reference: https://apidocs.beyonic.com/ To start using the Beyonic API Python API, you need to start

Harun Mbaabu Mwenda 46 Sep 1, 2022
Qwerkey is a social media platform for connecting and learning more about mechanical keyboards built on React and Redux in the frontend and Flask in the backend on top of a PostgreSQL database.

Flask React Project This is the backend for the Flask React project. Getting started Clone this repository (only this branch) git clone https://github

Peter Mai 22 Dec 20, 2022
Mixer -- Is a fixtures replacement. Supported Django, Flask, SqlAlchemy and custom python objects.

The Mixer is a helper to generate instances of Django or SQLAlchemy models. It's useful for testing and fixture replacement. Fast and convenient test-

Kirill Klenov 871 Dec 25, 2022
Single Page App with Flask and Vue.js

Developing a Single Page App with FastAPI and Vue.js Want to learn how to build this? Check out the post. Want to use this project? Build the images a

null 91 Jan 5, 2023
Flask + marshmallow for beautiful APIs

Flask-Marshmallow Flask + marshmallow for beautiful APIs Flask-Marshmallow is a thin integration layer for Flask (a Python web framework) and marshmal

marshmallow-code 768 Dec 22, 2022
A basic JSON-RPC implementation for your Flask-powered sites

Flask JSON-RPC A basic JSON-RPC implementation for your Flask-powered sites. Some reasons you might want to use: Simple, powerful, flexible and python

Cenobit Technologies 273 Dec 1, 2022
A Flask extension that enables or disables features based on configuration.

Flask FeatureFlags This is a Flask extension that adds feature flagging to your applications. This lets you turn parts of your site on or off based on

Rachel Greenfield 131 Sep 26, 2022
Regex Converter for Flask URL Routes

Flask-Reggie Enable Regex Routes within Flask Installation pip install flask-reggie Configuration To enable regex routes within your application from

Rhys Elsmore 48 Mar 7, 2022
Socket.IO integration for Flask applications.

Flask-SocketIO Socket.IO integration for Flask applications. Installation You can install this package as usual with pip: pip install flask-socketio

Miguel Grinberg 4.9k Jan 3, 2023
Pagination support for flask

flask-paginate Pagination support for flask framework (study from will_paginate). It supports several css frameworks. It requires Python2.6+ as string

Lix Xu 264 Nov 7, 2022
Adds GraphQL support to your Flask application.

Flask-GraphQL Adds GraphQL support to your Flask application. Usage Just use the GraphQLView view from flask_graphql from flask import Flask from flas

GraphQL Python 1.3k Dec 31, 2022
flask extension for integration with the awesome pydantic package

flask extension for integration with the awesome pydantic package

null 249 Jan 6, 2023
🚀 Cookiecutter Template for FastAPI + React Projects. Using PostgreSQL, SQLAlchemy, and Docker

FastAPI + React · A cookiecutter template for bootstrapping a FastAPI and React project using a modern stack. Features FastAPI (Python 3.8) JWT authen

Gabriel Abud 1.4k Jan 2, 2023
Full stack, modern web application generator. Using FastAPI, PostgreSQL as database, Docker, automatic HTTPS and more.

Full Stack FastAPI and PostgreSQL - Base Project Generator Generate a backend and frontend stack using Python, including interactive API documentation

Sebastián Ramírez 10.8k Jan 8, 2023
Cookiecutter API for creating Custom Skills for Azure Search using Python and Docker

cookiecutter-spacy-fastapi Python cookiecutter API for quick deployments of spaCy models with FastAPI Azure Search The API interface is compatible wit

Microsoft 379 Jan 3, 2023
Cookiecutter template for FastAPI projects using: Machine Learning, Poetry, Azure Pipelines and Pytests

cookiecutter-fastapi In order to create a template to FastAPI projects. ?? Important To use this project you don't need fork it. Just run cookiecutter

Arthur Henrique 225 Dec 28, 2022
🚀 Cookiecutter Template for FastAPI + React Projects. Using PostgreSQL, SQLAlchemy, and Docker

FastAPI + React · A cookiecutter template for bootstrapping a FastAPI and React project using a modern stack. Features FastAPI (Python 3.8) JWT authen

Gabriel Abud 448 Feb 19, 2021