标签归档:jinja2

如何在模板中将数据从Flask传递到JavaScript?

问题:如何在模板中将数据从Flask传递到JavaScript?

我的应用程序调用返回字典的API。我想将信息从此字典传递到视图中的JavaScript。具体来说,我在JS中使用Google Maps API,因此我希望向其传递一个包含长/短信息的元组列表。我知道render_template会将这些变量传递给视图,以便可以在HTML中使用它们,但是如何将它们传递给模板中的JavaScript?

from flask import Flask
from flask import render_template

app = Flask(__name__)

import foo_api

api = foo_api.API('API KEY')

@app.route('/')
def get_data():
    events = api.call(get_event, arg0, arg1)
    geocode = event['latitude'], event['longitude']
    return render_template('get_data.html', geocode=geocode)

My app makes a call to an API that returns a dictionary. I want to pass information from this dict to JavaScript in the view. I am using the Google Maps API in the JS, specifically, so I’d like to pass it a list of tuples with the long/lat information. I know that render_template will pass these variables to the view so they can be used in HTML, but how could I pass them to JavaScript in the template?

from flask import Flask
from flask import render_template

app = Flask(__name__)

import foo_api

api = foo_api.API('API KEY')

@app.route('/')
def get_data():
    events = api.call(get_event, arg0, arg1)
    geocode = event['latitude'], event['longitude']
    return render_template('get_data.html', geocode=geocode)

回答 0

您可以{{ variable }}在模板的任何地方使用,而不仅限于HTML部分。所以这应该工作:

<html>
<head>
  <script>
    var someJavaScriptVar = '{{ geocode[1] }}';
  </script>
</head>
<body>
  <p>Hello World</p>
  <button onclick="alert('Geocode: {{ geocode[0] }} ' + someJavaScriptVar)" />
</body>
</html>

可以将其视为两个阶段的过程:首先,Jinja(Flask使用的模板引擎)生成文本输出。这将发送给执行他所看到的JavaScript的用户。如果希望Flask变量作为数组在JavaScript中可用,则必须在输出中生成数组定义:

<html>
  <head>
    <script>
      var myGeocode = ['{{ geocode[0] }}', '{{ geocode[1] }}'];
    </script>
  </head>
  <body>
    <p>Hello World</p>
    <button onclick="alert('Geocode: ' + myGeocode[0] + ' ' + myGeocode[1])" />
  </body>
</html>

Jinja还提供了来自Python的更高级的构造,因此您可以将其缩短为:

<html>
<head>
  <script>
    var myGeocode = [{{ ', '.join(geocode) }}];
  </script>
</head>
<body>
  <p>Hello World</p>
  <button onclick="alert('Geocode: ' + myGeocode[0] + ' ' + myGeocode[1])" />
</body>
</html>

您还可以使用for循环,if语句等,请参阅Jinja2文档以获取更多信息。

另外,看看福特的答案,谁指出了tojson过滤器,它是对Jinja2标准过滤器集的补充。

编辑2018年11月:tojson现在已包含在Jinja2的标准过滤器集中。

You can use {{ variable }} anywhere in your template, not just in the HTML part. So this should work:

<html>
<head>
  <script>
    var someJavaScriptVar = '{{ geocode[1] }}';
  </script>
</head>
<body>
  <p>Hello World</p>
  <button onclick="alert('Geocode: {{ geocode[0] }} ' + someJavaScriptVar)" />
</body>
</html>

Think of it as a two-stage process: First, Jinja (the template engine Flask uses) generates your text output. This gets sent to the user who executes the JavaScript he sees. If you want your Flask variable to be available in JavaScript as an array, you have to generate an array definition in your output:

<html>
  <head>
    <script>
      var myGeocode = ['{{ geocode[0] }}', '{{ geocode[1] }}'];
    </script>
  </head>
  <body>
    <p>Hello World</p>
    <button onclick="alert('Geocode: ' + myGeocode[0] + ' ' + myGeocode[1])" />
  </body>
</html>

Jinja also offers more advanced constructs from Python, so you can shorten it to:

<html>
<head>
  <script>
    var myGeocode = [{{ ', '.join(geocode) }}];
  </script>
</head>
<body>
  <p>Hello World</p>
  <button onclick="alert('Geocode: ' + myGeocode[0] + ' ' + myGeocode[1])" />
</body>
</html>

You can also use for loops, if statements and many more, see the Jinja2 documentation for more.

Also, have a look at Ford’s answer who points out the tojson filter which is an addition to Jinja2’s standard set of filters.

Edit Nov 2018: tojson is now included in Jinja2’s standard set of filters.


回答 1

将几乎所有Python对象都转换为JavaScript对象的理想方法是使用JSON。JSON非常适合作为系统之间传输的格式,但有时我们会忘记它代表JavaScript Object Notation。这意味着将JSON注入模板与注入描述对象的JavaScript代码相同。

Flask为此提供了一个Jinja过滤器:tojson将结构转储到JSON字符串并标记为安全,以便Jinja不会自动转义它。

<html>
  <head>
    <script>
      var myGeocode = {{ geocode|tojson }};
    </script>
  </head>
  <body>
    <p>Hello World</p>
    <button onclick="alert('Geocode: ' + myGeocode[0] + ' ' + myGeocode[1])" />
  </body>
</html>

这适用于JSON可序列化的任何Python结构:

python_data = {
    'some_list': [4, 5, 6],
    'nested_dict': {'foo': 7, 'bar': 'a string'}
}
var data = {{ python_data|tojson }};
alert('Data: ' + data.some_list[1] + ' ' + data.nested_dict.foo + 
      ' ' + data.nested_dict.bar);

The ideal way to go about getting pretty much any Python object into a JavaScript object is to use JSON. JSON is great as a format for transfer between systems, but sometimes we forget that it stands for JavaScript Object Notation. This means that injecting JSON into the template is the same as injecting JavaScript code that describes the object.

Flask provides a Jinja filter for this: tojson dumps the structure to a JSON string and marks it safe so that Jinja does not autoescape it.

<html>
  <head>
    <script>
      var myGeocode = {{ geocode|tojson }};
    </script>
  </head>
  <body>
    <p>Hello World</p>
    <button onclick="alert('Geocode: ' + myGeocode[0] + ' ' + myGeocode[1])" />
  </body>
</html>

This works for any Python structure that is JSON serializable:

python_data = {
    'some_list': [4, 5, 6],
    'nested_dict': {'foo': 7, 'bar': 'a string'}
}
var data = {{ python_data|tojson }};
alert('Data: ' + data.some_list[1] + ' ' + data.nested_dict.foo + 
      ' ' + data.nested_dict.bar);

回答 2

在HTML元素上使用data属性可以避免使用内联脚本,这反过来意味着您可以使用更严格的CSP规则来提高安全性。

指定数据属性,如下所示:

<div id="mydiv" data-geocode='{{ geocode|tojson }}'>...</div>

然后像下面这样在静态JavaScript文件中进行访问:

// Raw JavaScript
var geocode = JSON.parse(document.getElementById("mydiv").dataset.geocode);

// jQuery
var geocode = JSON.parse($("#mydiv").data("geocode"));

Using a data attribute on an HTML element avoids having to use inline scripting, which in turn means you can use stricter CSP rules for increased security.

Specify a data attribute like so:

<div id="mydiv" data-geocode='{{ geocode|tojson }}'>...</div>

Then access it in a static JavaScript file like so:

// Raw JavaScript
var geocode = JSON.parse(document.getElementById("mydiv").dataset.geocode);

// jQuery
var geocode = JSON.parse($("#mydiv").data("geocode"));

回答 3

另外,您可以添加一个端点以返回变量:

@app.route("/api/geocode")
def geo_code():
    return jsonify(geocode)

然后执行XHR检索它:

fetch('/api/geocode')
  .then((res)=>{ console.log(res) })

Alternatively you could add an endpoint to return your variable:

@app.route("/api/geocode")
def geo_code():
    return jsonify(geocode)

Then do an XHR to retrieve it:

fetch('/api/geocode')
  .then((res)=>{ console.log(res) })

回答 4

对于那些想要将变量传递给使用flask来源的脚本的人来说,这是另一种替代解决方案,我只能通过在外部定义变量,然后按如下所示调用脚本来设法使它起作用:

    <script>
    var myfileuri = "/static/my_csv.csv"
    var mytableid = 'mytable';
    </script>
    <script type="text/javascript" src="/static/test123.js"></script>

如果我在test123.js其中输入jinja变量不起作用,则会收到错误消息。

Just another alternative solution for those who want to pass variables to a script which is sourced using flask, I only managed to get this working by defining the variables outside and then calling the script as follows:

    <script>
    var myfileuri = "/static/my_csv.csv"
    var mytableid = 'mytable';
    </script>
    <script type="text/javascript" src="/static/test123.js"></script>

If I input jinja variables in test123.js it doesn’t work and you will get an error.


回答 5

已经给出了有效的答案,但是我想添加一个检查,以在烧瓶变量不可用的情况下充当故障保险。使用时:

var myVariable = {{ flaskvar | tojson }};

如果存在导致变量不存在的错误,则导致的错误可能会产生意外的结果。为避免这种情况:

{% if flaskvar is defined and flaskvar %}
var myVariable = {{ flaskvar | tojson }};
{% endif %}

Working answers are already given but I want to add a check that acts as a fail-safe in case the flask variable is not available. When you use:

var myVariable = {{ flaskvar | tojson }};

if there is an error that causes the variable to be non existent, resulting errors may produce unexpected results. To avoid this:

{% if flaskvar is defined and flaskvar %}
var myVariable = {{ flaskvar | tojson }};
{% endif %}

回答 6

<script>
    const geocodeArr = JSON.parse('{{ geocode | tojson }}');
    console.log(geocodeArr);
</script>

这使用jinja2将地理编码元组转换为json字符串,然后javascript JSON.parse将其转换为javascript数组。

<script>
    const geocodeArr = JSON.parse('{{ geocode | tojson }}');
    console.log(geocodeArr);
</script>

This uses jinja2 to turn the geocode tuple into a json string, and then the javascript JSON.parse turns that into a javascript array.


回答 7

好吧,我有一个棘手的方法来完成这项工作。这个想法如下

<label>, <p>, <input>在HTML主体中制作一些不可见的HTML标记(如etc),并在标记ID中创建模式,例如,在标记ID中使用列表索引,在标记类名称中使用列表值。

在这里,我有两个长度相同的清单maintenance_next []和maintenance_block_time []。我想使用烧瓶将这两个列表的数据传递给javascript。因此,我采取了一些不可见的标签标记并将其标记名称设置为列表索引的模式,并将其类名称设置为index的值。

{% for i in range(maintenance_next|length): %}
<label id="maintenance_next_{{i}}" name="{{maintenance_next[i]}}" style="display: none;"></label>
<label id="maintenance_block_time_{{i}}" name="{{maintenance_block_time[i]}}" style="display: none;"></label>
{% endfor%}

之后,我使用一些简单的javascript操作检索javascript中的数据。

<script>
var total_len = {{ total_len }};

for (var i = 0; i < total_len; i++) {
    var tm1 = document.getElementById("maintenance_next_" + i).getAttribute("name");
    var tm2 = document.getElementById("maintenance_block_time_" + i).getAttribute("name");
    
    //Do what you need to do with tm1 and tm2.
    
    console.log(tm1);
    console.log(tm2);
}
</script>

Well, I have a tricky method for this job. The idea is as follow-

Make some invisible HTML tags like <label>, <p>, <input> etc. in HTML body and make a pattern in tag id, for example, use list index in tag id and list value at tag class name.

Here I have two lists maintenance_next[] and maintenance_block_time[] of the same length. I want to pass these two list’s data to javascript using the flask. So I take some invisible label tag and set its tag name is a pattern of list index and set its class name as value at index.

{% for i in range(maintenance_next|length): %}
<label id="maintenance_next_{{i}}" name="{{maintenance_next[i]}}" style="display: none;"></label>
<label id="maintenance_block_time_{{i}}" name="{{maintenance_block_time[i]}}" style="display: none;"></label>
{% endfor%}

After this, I retrieve the data in javascript using some simple javascript operation.

<script>
var total_len = {{ total_len }};

for (var i = 0; i < total_len; i++) {
    var tm1 = document.getElementById("maintenance_next_" + i).getAttribute("name");
    var tm2 = document.getElementById("maintenance_block_time_" + i).getAttribute("name");
    
    //Do what you need to do with tm1 and tm2.
    
    console.log(tm1);
    console.log(tm2);
}
</script>

回答 8

一些js文件来自网络或库,它们不是您自己编写的。他们获得的代码如下所示:

var queryString = document.location.search.substring(1);
var params = PDFViewerApplication.parseQueryString(queryString);
var file = 'file' in params ? params.file : DEFAULT_URL;

此方法使js文件保持不变(保持独立性),并正确传递变量!

Some js files come from the web or library, they are not written by yourself. The code they get variable like this:

var queryString = document.location.search.substring(1);
var params = PDFViewerApplication.parseQueryString(queryString);
var file = 'file' in params ? params.file : DEFAULT_URL;

This method makes js files unchanged(keep independence), and pass variable correctly!


将整数转换为字符串Jinja

问题:将整数转换为字符串Jinja

我有一个整数

{% set curYear = 2013 %}

{% if %}声明中,我必须将其与一些字符串进行比较。我不能curYear在开始时设置为字符串,因为我必须在循环中将其递减。

如何转换?

I have an integer

{% set curYear = 2013 %}

In {% if %} statement I have to compare it with some string. I can’t set curYear to string at the beginning because I have to decrement it in loop.

How can I convert it?


回答 0

我找到了答案。

将整数转换为字符串:

myOldIntValue|string

将字串转换为整数:

myOldStrValue|int

I found the answer.

Cast integer to string:

myOldIntValue|string

Cast string to integer:

myOldStrValue|int

回答 1

OP需要在外部强制转换为字符串{% set ... %}。但是,如果不是您的情况,您可以执行以下操作:

{% set curYear = 2013 | string() %}

请注意,您需要在该Jinja过滤器上加上括号。

如果要串联2个变量,则还可以使用~ custom运算符

The OP needed to cast as string outside the {% set ... %}. But if that not your case you can do:

{% set curYear = 2013 | string() %}

Note that you need the parenthesis on that jinja filter.

If you’re concatenating 2 variables, you can also use the ~ custom operator.


模板文件更改时重新加载Flask应用

问题:模板文件更改时重新加载Flask应用

默认情况下,使用内置服务器(Flask.run)运行Flask应用程序时,它将监视其Python文件并在代码更改时自动重新加载该应用程序:

* Detected change in '/home/xion/hello-world/app.py', reloading
* Restarting with reloader

不幸的是,这似乎仅适用于* .py文件,而且我似乎没有找到任何将此功能扩展到其他文件的方法。最值得注意的是,当模板更改时,让Flask重新启动应用程序将非常有用。我已经迷失了多少次我不喜欢模板中的标记,却因为看不到任何更改而感到困惑,只是发现该应用程序仍在使用旧版本的Jinja模板。

因此,有没有办法在模板目录中包含Flask监视文件,还是需要深入研究框架的源代码?

编辑:我正在使用Ubuntu 10.10。尚未在任何其他平台上尝试过。


经过进一步的查询,我发现模板中的更改确实实时更新的,而无需重新加载应用程序本身。但是,这似乎仅适用于传递给的模板flask.render_template

但是碰巧的是,在我的应用程序中,我有很多在Jinja模板中使用的可重用的,参数化的组件。它们实现为{% macro %}s,驻留在专用的“模块”中,并{% import %}编入实际页面。很好,很干…除了那些导入的模板显然从未检查过是否修改,因为它们根本没有通过render_template

(奇怪的是,对于通过调用的模板,这种情况不会发生{% extends %}。至于{% include %},由于不真正使用它们,我不知道。)

因此,总结起来,这种现象的根源似乎在Jinja和Flask或Werkzeug之间。我想对于其中的任何一个项目,都可能需要进行bug跟踪:)同时,我已经接受了jd。的答案,因为这是我实际使用的解决方案-而且它的工作原理很像魅力。

By default, when running Flask application using the built-in server (Flask.run), it monitors its Python files and automatically reloads the app if its code changes:

* Detected change in '/home/xion/hello-world/app.py', reloading
* Restarting with reloader

Unfortunately, this seems to work for *.py files only, and I don’t seem to find any way to extend this functionality to other files. Most notably, it would be extremely useful to have Flask restart the app when a template changes. I’ve lost count on how many times I was fiddling with markup in templates and getting confused by not seeing any changes, only to find out that the app was still using the old version of Jinja template.

So, is there a way to have Flask monitor files in templates directory, or does it require diving into the framework’s source?

Edit: I’m using Ubuntu 10.10. Haven’t tried that on any other platforms really.


After further inquiry, I have discovered that changes in templates indeed are updated in real time, without reloading the app itself. However, this seems to apply only to those templates that are passed to flask.render_template.

But it so happens that in my app, I have quite a lot of reusable, parametrized components which I use in Jinja templates. They are implemented as {% macro %}s, reside in dedicated “modules” and are {% import %}ed into actual pages. All nice and DRY… except that those imported templates are apparently never checked for modifications, as they don’t pass through render_template at all.

(Curiously, this doesn’t happen for templates invoked through {% extends %}. As for {% include %}, I have no idea as I don’t really use them.)

So to wrap up, the roots of this phenomenon seems to lie somewhere between Jinja and Flask or Werkzeug. I guess it may warrant a trip to bug tracker for either of those projects :) Meanwhile, I’ve accepted the jd.‘s answer because that’s the solution I actually used – and it works like a charm.


回答 0

以我的经验,模板甚至不需要重新启动应用程序即可刷新,因为每次render_template()调用时都应从磁盘加载模板。也许您的模板使用方式有所不同。

要在模板更改(或其他文件)时重新加载应用程序,可以将extra_files参数传递给Flask().run(),以观察文件名的集合:这些文件上的任何更改都会触发重新加载器。

例:

from os import path, walk

extra_dirs = ['directory/to/watch',]
extra_files = extra_dirs[:]
for extra_dir in extra_dirs:
    for dirname, dirs, files in walk(extra_dir):
        for filename in files:
            filename = path.join(dirname, filename)
            if path.isfile(filename):
                extra_files.append(filename)
app.run(extra_files=extra_files)

参见此处:http : //werkzeug.pocoo.org/docs/0.10/serving/?highlight=run_simple#werkzeug.serving.run_simple

In my experience, templates don’t even need the application to restart to be refreshed, as they should be loaded from disk everytime render_template() is called. Maybe your templates are used differently though.

To reload your application when the templates change (or any other file), you can pass the extra_files argument to Flask().run(), a collection of filenames to watch: any change on those files will trigger the reloader.

Example:

from os import path, walk

extra_dirs = ['directory/to/watch',]
extra_files = extra_dirs[:]
for extra_dir in extra_dirs:
    for dirname, dirs, files in walk(extra_dir):
        for filename in files:
            filename = path.join(dirname, filename)
            if path.isfile(filename):
                extra_files.append(filename)
app.run(extra_files=extra_files)

See here: http://werkzeug.pocoo.org/docs/0.10/serving/?highlight=run_simple#werkzeug.serving.run_simple


回答 1

您可以使用

TEMPLATES_AUTO_RELOAD = True

http://flask.pocoo.org/docs/1.0/config/

是否检查模板源的修改并自动重新加载。默认情况下,该值为“无”,这意味着Flask仅在调试模式下检查原始文件。

you can use

TEMPLATES_AUTO_RELOAD = True

From http://flask.pocoo.org/docs/1.0/config/

Whether to check for modifications of the template source and reload it automatically. By default the value is None which means that Flask checks original file only in debug mode.


回答 2

使用jinja模板时,需要设置一些参数。就python3而言,我使用以下代码解决了它:

if __name__ == '__main__':
    app.jinja_env.auto_reload = True
    app.config['TEMPLATES_AUTO_RELOAD'] = True
    app.run(debug=True, host='0.0.0.0')

When you are working with jinja templates, you need to set some parameters. In my case with python3, I solved it with the following code:

if __name__ == '__main__':
    app.jinja_env.auto_reload = True
    app.config['TEMPLATES_AUTO_RELOAD'] = True
    app.run(debug=True, host='0.0.0.0')

回答 3

对我来说效果很好:

 from flask import Flask, render_template, request, url_for, redirect
 app = Flask(__name__)
 app.config["TEMPLATES_AUTO_RELOAD"] = True

请参阅http://flask.pocoo.org/docs/1.0/config/

For me works just fine:

 from flask import Flask, render_template, request, url_for, redirect
 app = Flask(__name__)
 app.config["TEMPLATES_AUTO_RELOAD"] = True

See more on http://flask.pocoo.org/docs/1.0/config/


回答 4

实际上对我来说TEMPLATES_AUTO_RELOAD = True不起作用(0.12版本)。我使用jinja2和我所做的事情:

  1. 创建功能 before_request

    def before_request():
        app.jinja_env.cache = {}
  2. 在应用程序中注册

    app.before_request(before_request)
  3. 而已。

Actually for me TEMPLATES_AUTO_RELOAD = True does not work (0.12 version). I use jinja2 and what i have done:

  1. Create function before_request

    def before_request():
        app.jinja_env.cache = {}
    
  2. Register it in application

    app.before_request(before_request)
    
  3. That’s it.


回答 5

对我有用的只是添加以下内容:

@app.before_request
def before_request():
    # When you import jinja2 macros, they get cached which is annoying for local
    # development, so wipe the cache every request.
    if 'localhost' in request.host_url or '0.0.0.0' in request.host_url:
        app.jinja_env.cache = {}

摘自@dikkini的回答

What worked for me is just adding this:

@app.before_request
def before_request():
    # When you import jinja2 macros, they get cached which is annoying for local
    # development, so wipe the cache every request.
    if 'localhost' in request.host_url or '0.0.0.0' in request.host_url:
        app.jinja_env.cache = {}

(taken from @dikkini’s answer)


回答 6

在Windows上使用最新版本的Flask,并将run命令和debug设置为true;无需重置Flask即可生效对模板的更改。尝试按Shift + F5(或Shift加重新加载按钮)以确保没有任何内容被缓存。

Using the latest version of Flask on Windows, using the run command and debug set to true; Flask doesn’t need to be reset for changes to templates to be brought in to effect. Try Shift+F5 (or Shift plus the reload button) to make sure nothing it being cached.


回答 7

参见http://flask.pocoo.org/docs/1.0/quickstart/ 并使用FLASK_ENV=development


回答 8

截至2019年6月更新:

建议在app.run()上使用烧瓶CLI,以运行开发服务器,因此,如果我们要使用CLI,则不能使用接受的解决方案。

在撰写本文时,使用Flask(1.1)的开发版本允许我们设置环境变量FLASK_RUN_EXTRA_FILES,该变量有效地执行与接受的答案相同的操作。

请参阅此github问题

用法示例:

export FLASK_RUN_EXTRA_FILES="app/templates/index.html"
flask run

在Linux中。要指定多个其他文件,请使用冒号分隔文件路径。,例如

export FLASK_RUN_EXTRA_FILES="app/templates/index.html:app/templates/other.html"

CLI还支持--extra-filesFlask 1.1以后的参数。

Updated as of June 2019:

The flask CLI is recommended over app.run() for running a dev server, so if we want to use the CLI then the accepted solution can’t be used.

Using the development version of Flask (1.1) as of this writing allows us to set an environment variable FLASK_RUN_EXTRA_FILES which effectively does the same thing as the accepted answer.

See this github issue.

Example usage:

export FLASK_RUN_EXTRA_FILES="app/templates/index.html"
flask run

in Linux. To specify multiple extra files, separate file paths with colons., e.g.

export FLASK_RUN_EXTRA_FILES="app/templates/index.html:app/templates/other.html"

The CLI also supports an --extra-files argument as of Flask 1.1.


回答 9

模板会自动重新加载,为什么不ctrl+f5刷新网页,导致Web浏览器通常保存缓存。

Templates are reloaded automatically, why not doing ctrl+f5 to refresh the webpage, cause web-browsers usually save cache.


如何在python jinja模板中输出loop.counter?

问题:如何在python jinja模板中输出loop.counter?

我希望能够将当前循环迭代输出到我的模板。

根据文档:http : //wsgiarea.pocoo.org/jinja/docs/loops.html,我正在尝试使用一个loop.counter变量。

我有以下几点:

<ul>
{% for user in userlist %}
  <li>
      {{ user }} {{loop.counter}}
  </li>
      {% if loop.counter == 1 %}
          This is the First user
      {% endif %}
{% endfor %}
</ul>

虽然没有任何输出到我的模板。正确的语法是什么?

I want to be able to output the current loop iteration to my template.

According to the docs: http://wsgiarea.pocoo.org/jinja/docs/loops.html, there is a loop.counter variable that I am trying to use.

I have the following:

<ul>
{% for user in userlist %}
  <li>
      {{ user }} {{loop.counter}}
  </li>
      {% if loop.counter == 1 %}
          This is the First user
      {% endif %}
{% endfor %}
</ul>

Though nothing is being output to my template. What is the correct syntax?


回答 0

循环内部的计数器变量在jinja2中称为loop.index

>>> from jinja2 import Template

>>> s = "{% for element in elements %}{{loop.index}} {% endfor %}"
>>> Template(s).render(elements=["a", "b", "c", "d"])
1 2 3 4

有关更多信息,请参见http://jinja.pocoo.org/docs/templates/

The counter variable inside the loop is called loop.index in jinja2.

>>> from jinja2 import Template

>>> s = "{% for element in elements %}{{loop.index}} {% endfor %}"
>>> Template(s).render(elements=["a", "b", "c", "d"])
1 2 3 4

See http://jinja.pocoo.org/docs/templates/ for more.


回答 1

在for循环块中,您可以访问一些特殊变量,包括loop.index–but no loop.counter。从官方文档

Variable    Description
loop.index  The current iteration of the loop. (1 indexed)
loop.index0 The current iteration of the loop. (0 indexed)
loop.revindex   The number of iterations from the end of the loop (1 indexed)
loop.revindex0  The number of iterations from the end of the loop (0 indexed)
loop.first  True if first iteration.
loop.last   True if last iteration.
loop.length The number of items in the sequence.
loop.cycle  A helper function to cycle between a list of sequences. See the explanation below.
loop.depth  Indicates how deep in a recursive loop the rendering currently is. Starts at level 1
loop.depth0 Indicates how deep in a recursive loop the rendering currently is. Starts at level 0
loop.previtem   The item from the previous iteration of the loop. Undefined during the first iteration.
loop.nextitem   The item from the following iteration of the loop. Undefined during the last iteration.
loop.changed(*val)  True if previously called with a different value (or not called at all).

Inside of a for-loop block, you can access some special variables including loop.index –but no loop.counter. From the official docs:

Variable    Description
loop.index  The current iteration of the loop. (1 indexed)
loop.index0 The current iteration of the loop. (0 indexed)
loop.revindex   The number of iterations from the end of the loop (1 indexed)
loop.revindex0  The number of iterations from the end of the loop (0 indexed)
loop.first  True if first iteration.
loop.last   True if last iteration.
loop.length The number of items in the sequence.
loop.cycle  A helper function to cycle between a list of sequences. See the explanation below.
loop.depth  Indicates how deep in a recursive loop the rendering currently is. Starts at level 1
loop.depth0 Indicates how deep in a recursive loop the rendering currently is. Starts at level 0
loop.previtem   The item from the previous iteration of the loop. Undefined during the first iteration.
loop.nextitem   The item from the following iteration of the loop. Undefined during the last iteration.
loop.changed(*val)  True if previously called with a different value (or not called at all).

回答 2

如果您使用的是Django,请使用forloop.counter代替loop.counter

<ul>
{% for user in userlist %}
  <li>
      {{ user }} {{forloop.counter}}
  </li>
      {% if forloop.counter == 1 %}
          This is the First user
      {% endif %}
{% endfor %}
</ul>

if you are using django use forloop.counter instead of loop.counter

<ul>
{% for user in userlist %}
  <li>
      {{ user }} {{forloop.counter}}
  </li>
      {% if forloop.counter == 1 %}
          This is the First user
      {% endif %}
{% endfor %}
</ul>

使用Flask / Jinja2将HTML传递到模板

问题:使用Flask / Jinja2将HTML传递到模板

我正在为Flask和SQLAlchemy构建一个管理员,我想使用来将不同输入的HTML传递给我的视图render_template。模板框架似乎会自动转义html,因此所有<“’>都将转换为html实体。如何禁用它以使HTML正确呈现?

I’m building an admin for Flask and SQLAlchemy, and I want to pass the HTML for the different inputs to my view using render_template. The templating framework seems to escape the html automatically, so all <“‘> are converted to html entities. How can I disable that so that the HTML renders correctly?


回答 0

理想的方法是

{{ something|safe }}

而不是完全关闭自动转义。

the ideal way is to

{{ something|safe }}

than completely turning off auto escaping.


回答 1

您还可以从代码中将其声明为HTML安全的:

from flask import Markup
value = Markup('<strong>The HTML String</strong>')

然后将该值传递给模板,而他们不必这样做|safe

You can also declare it HTML safe from the code:

from flask import Markup
value = Markup('<strong>The HTML String</strong>')

Then pass that value to the templates and they don’t have to |safe it.


回答 2

从jinja docs部分HTML Escaping

启用自动转义后,默认情况下所有内容都将转义,除非明确标记为安全的值。可以通过应用程序或使用安全过滤器在模板中对其进行标记。

例:

 <div class="info">
   {{data.email_content|safe}}
 </div>

From the jinja docs section HTML Escaping:

When automatic escaping is enabled everything is escaped by default except for values explicitly marked as safe. Those can either be marked by the application or in the template by using the |safe filter.

Example:

 <div class="info">
   {{data.email_content|safe}}
 </div>

回答 3

当您有很多不需要转义的变量时,可以使用一个autoescape块:

{% autoescape off %}
{{ something }}
{{ something_else }}
<b>{{ something_important }}</b>
{% endautoescape %}

When you have a lot of variables that don’t need escaping, you can use an autoescape block:

{% autoescape off %}
{{ something }}
{{ something_else }}
<b>{{ something_important }}</b>
{% endautoescape %}

回答 4

有些人似乎关闭了自动转义功能,这会带来安全风险可能会影响字符串显示。

如果您只想在字符串中插入一些换行符并将其转换为<br />,则可以使用jinja宏,例如:

{% macro linebreaks_for_string( the_string ) -%}
{% if the_string %}
{% for line in the_string.split('\n') %}
<br />
{{ line }}
{% endfor %}
{% else %}
{{ the_string }}
{% endif %}
{%- endmacro %}

在您的模板中只需使用

{{ linebreaks_for_string( my_string_in_a_variable ) }}

Some people seem to turn autoescape off which carries security risks to manipulate the string display.

If you only want to insert some linebreaks into a string and convert the linebreaks into <br />, then you could take a jinja macro like:

{% macro linebreaks_for_string( the_string ) -%}
{% if the_string %}
{% for line in the_string.split('\n') %}
<br />
{{ line }}
{% endfor %}
{% else %}
{{ the_string }}
{% endif %}
{%- endmacro %}

and in your template just call this with

{{ linebreaks_for_string( my_string_in_a_variable ) }}

从jinja2调用python函数

问题:从jinja2调用python函数

我正在使用jinja2,并且想使用类似于调用宏的语法来调用python函数作为辅助函数。jinja2似乎旨在阻止我进行函数调用,并坚持要通过将函数复制到模板中作为宏来重复我自己。

有没有简单的方法可以做到这一点?而且,有没有什么方法可以导入整套python函数并使它们从jinja2中进行访问,而无需经历大量的rigamarole(例如编写扩展名)?

I am using jinja2, and I want to call a python function as a helper, using a similar syntax as if I were calling a macro. jinja2 seems intent on preventing me from making a function call, and insists I repeat myself by copying the function into a template as a macro.

Is there any straightforward way to do this? And, is there any way to import a whole set of python functions and have them accessible from jinja2, without going through a whole lot of rigamarole (such as writing an extension)?


回答 0

对于使用Flask的用户,请将其放入您的__init__.py

def clever_function():
    return u'HELLO'

app.jinja_env.globals.update(clever_function=clever_function)

然后在您的模板中调用 {{ clever_function() }}

For those using Flask, put this in your __init__.py:

def clever_function():
    return u'HELLO'

app.jinja_env.globals.update(clever_function=clever_function)

and in your template call it with {{ clever_function() }}


回答 1

注意:这是Flask特有的!

我知道这篇文章已经很老了,但是在新版本的Flask中使用上下文处理器可以做到这一点。

可以轻松创建变量:

@app.context_processor
def example():
    return dict(myexample='This is an example')

上面的代码可以在Flask的Jinja2模板中使用,如下所示:

{{ myexample }}

(哪个输出This is an example

以及完整的功能:

@app.context_processor
def utility_processor():
    def format_price(amount, currency=u'€'):
        return u'{0:.2f}{1}'.format(amount, currency)
    return dict(format_price=format_price)

上面这样使用时:

{{ format_price(0.33) }}

(输出带有货币符号的输入价格)

另外,您也可以使用Flask中的jinja过滤器。例如使用装饰器:

@app.template_filter('reverse')
def reverse_filter(s):
    return s[::-1]

或者,没有装饰器,并手动注册该功能:

def reverse_filter(s):
    return s[::-1]
app.jinja_env.filters['reverse'] = reverse_filter

通过以上两种方法应用的过滤器可以像这样使用:

{% for x in mylist | reverse %}
{% endfor %}

Note: This is Flask specific!

I know this post is quite old, but there are better methods of doing this in the newer versions of Flask using context processors.

Variables can easily be created:

@app.context_processor
def example():
    return dict(myexample='This is an example')

The above can be used in a Jinja2 template with Flask like so:

{{ myexample }}

(Which outputs This is an example)

As well as full fledged functions:

@app.context_processor
def utility_processor():
    def format_price(amount, currency=u'€'):
        return u'{0:.2f}{1}'.format(amount, currency)
    return dict(format_price=format_price)

The above when used like so:

{{ format_price(0.33) }}

(Which outputs the input price with the currency symbol)

Alternatively, you can use jinja filters, baked into Flask. E.g. using decorators:

@app.template_filter('reverse')
def reverse_filter(s):
    return s[::-1]

Or, without decorators, and manually registering the function:

def reverse_filter(s):
    return s[::-1]
app.jinja_env.filters['reverse'] = reverse_filter

Filters applied with the above two methods can be used like this:

{% for x in mylist | reverse %}
{% endfor %}

回答 2

我认为jinja故意使在模板内运行“任意” python变得困难。它试图证明以下观点:模板中的逻辑更少是一件好事。

您可以在 Environment实例中以添加对函数的引用。必须加载任何模板之前完成此操作。例如:

from jinja2 import Environment, FileSystemLoader

def clever_function(a, b):
    return u''.join([b, a])

env = Environment(loader=FileSystemLoader('/path/to/templates'))
env.globals['clever_function'] = clever_function

I think jinja deliberately makes it difficult to run ‘arbitrary’ python within a template. It tries to enforce the opinion that less logic in templates is a good thing.

You can manipulate the global namespace within an Environment instance to add references to your functions. It must be done before you load any templates. For example:

from jinja2 import Environment, FileSystemLoader

def clever_function(a, b):
    return u''.join([b, a])

env = Environment(loader=FileSystemLoader('/path/to/templates'))
env.globals['clever_function'] = clever_function

回答 3

from jinja2 import Template

def custom_function(a):
    return a.replace('o', 'ay')

template = Template('Hey, my name is {{ custom_function(first_name) }} {{ func2(last_name) }}')
template.globals['custom_function'] = custom_function

您还可以根据Matroskin的答案在字段中提供功能

fields = {'first_name': 'Jo', 'last_name': 'Ko', 'func2': custom_function}
print template.render(**fields)

将输出:

Hey, my name is Jay Kay

适用于Jinja2版本2.7.3

而且,如果您想让装饰者简化对功能的定义,template.globals请查看Bruno Bronosky的答案

from jinja2 import Template

def custom_function(a):
    return a.replace('o', 'ay')

template = Template('Hey, my name is {{ custom_function(first_name) }} {{ func2(last_name) }}')
template.globals['custom_function'] = custom_function

You can also give the function in the fields as per Matroskin’s answer

fields = {'first_name': 'Jo', 'last_name': 'Ko', 'func2': custom_function}
print template.render(**fields)

Will output:

Hey, my name is Jay Kay

Works with Jinja2 version 2.7.3

And if you want a decorator to ease defining functions on template.globals check out Bruno Bronosky’s answer


回答 4

我喜欢@AJP的答案。我逐字使用它,直到获得了很多功能。然后我切换到Python函数装饰器

from jinja2 import Template

template = '''
Hi, my name is {{ custom_function1(first_name) }}
My name is {{ custom_function2(first_name) }}
My name is {{ custom_function3(first_name) }}
'''
jinga_html_template = Template(template)

def template_function(func):
    jinga_html_template.globals[func.__name__] = func
    return func

@template_function
def custom_function1(a):
    return a.replace('o', 'ay')

@template_function
def custom_function2(a):
    return a.replace('o', 'ill')

@template_function
def custom_function3(a):
    return 'Slim Shady'

fields = {'first_name': 'Jo'}
print(jinga_html_template.render(**fields))

好东西功能都有__name__

I like @AJP’s answer. I used it verbatim until I ended up with a lot of functions. Then I switched to a Python function decorator.

from jinja2 import Template

template = '''
Hi, my name is {{ custom_function1(first_name) }}
My name is {{ custom_function2(first_name) }}
My name is {{ custom_function3(first_name) }}
'''
jinga_html_template = Template(template)

def template_function(func):
    jinga_html_template.globals[func.__name__] = func
    return func

@template_function
def custom_function1(a):
    return a.replace('o', 'ay')

@template_function
def custom_function2(a):
    return a.replace('o', 'ill')

@template_function
def custom_function3(a):
    return 'Slim Shady'

fields = {'first_name': 'Jo'}
print(jinga_html_template.render(**fields))

Good thing functions have a __name__!


回答 5

从来没有在官方文档或堆栈溢出中看到过如此简单的方法,但是当我发现这一点时,我感到惊讶:

# jinja2.__version__ == 2.8
from jinja2 import Template

def calcName(n, i):
    return ' '.join([n] * i)

template = Template("Hello {{ calcName('Gandalf', 2) }}")

template.render(calcName=calcName)
# or
template.render({'calcName': calcName})

Never saw such simple way at official docs or at stack overflow, but i was amazed when found this:

# jinja2.__version__ == 2.8
from jinja2 import Template

def calcName(n, i):
    return ' '.join([n] * i)

template = Template("Hello {{ calcName('Gandalf', 2) }}")

template.render(calcName=calcName)
# or
template.render({'calcName': calcName})

回答 6

使用Lambda将模板连接到您的主代码

return render_template("clever_template", clever_function=lambda x: clever_function x)

然后,您可以无缝调用模板中的函数

{{clever_function(value)}}

Use a lambda to connect the template to your main code

return render_template("clever_template", clever_function=lambda x: clever_function x)

Then you can seamlessly call the function in the template

{{clever_function(value)}}

回答 7

要从Jinja2调用python函数,您可以使用自定义过滤器,其工作原理与全局变量类似: http //jinja.pocoo.org/docs/dev/api/#writing-filters

这非常简单和有用。在文件myTemplate.txt中,我写道:

{{ data|pythonFct }}

并在python脚本中:

import jinja2

def pythonFct(data):
    return "This is my data: {0}".format(data)

input="my custom filter works!"

loader = jinja2.FileSystemLoader(path or './')
env = jinja2.Environment(loader=loader)
env.filters['pythonFct'] = pythonFct
result = env.get_template("myTemplate.txt").render(data=input)
print(result)

To call a python function from Jinja2, you can use custom filters which work similarly as the globals: http://jinja.pocoo.org/docs/dev/api/#writing-filters

It’s quite simple and useful. In a file myTemplate.txt, I wrote:

{{ data|pythonFct }}

And in a python script:

import jinja2

def pythonFct(data):
    return "This is my data: {0}".format(data)

input="my custom filter works!"

loader = jinja2.FileSystemLoader(path or './')
env = jinja2.Environment(loader=loader)
env.filters['pythonFct'] = pythonFct
result = env.get_template("myTemplate.txt").render(data=input)
print(result)

回答 8

有什么方法可以导入整套python函数,并可以从jinja2访问它们?

是的,除了上面的其他答案之外,这对我也有用。

创建一个类并使用相关方法填充它,例如

class Test_jinja_object:

    def __init__(self):
        self.myvar = 'sample_var'

    def clever_function (self):
        return 'hello' 

然后在视图函数中创建类的实例,并将结果对象作为render_template函数的参数传递给模板

my_obj = Test_jinja_object()

现在,在模板中,您可以像这样调用jinja中的类方法

{{ my_obj.clever_function () }}

is there any way to import a whole set of python functions and have them accessible from jinja2 ?

Yes there is, In addition to the other answers above, this works for me.

Create a class and populate it with the associated methods e.g

class Test_jinja_object:

    def __init__(self):
        self.myvar = 'sample_var'

    def clever_function (self):
        return 'hello' 

Then create an instance of your class in your view function and pass the resultant object to your template as a parameter for the render_template function

my_obj = Test_jinja_object()

Now in your template, you can call the class methods in jinja like so

{{ my_obj.clever_function () }}

回答 9

要导入所有内置函数,可以使用:

app.jinja_env.globals.update(__builtins__)

如果这不起作用,请.__dict__在之后添加__builtins__

基于John32323的答案

To import all the builtin functions you can use:

app.jinja_env.globals.update(__builtins__)

Add .__dict__ after __builtins__ if this doesn’t work.

Based on John32323’s answer.


回答 10

如果使用Django,则只需将函数与上下文一起传递即可:

context = {
    'title':'My title',
    'str': str,
}
...
return render(request, 'index.html', context)

现在您将能够使用strjinja2模板中的功能

If you are doing it with Django, you can just pass the function with the context:

context = {
    'title':'My title',
    'str': str,
}
...
return render(request, 'index.html', context)

Now you will be able to use the str function in jinja2 template


回答 11

有一个更简单的决定。

@app.route('/x')
def x():
    return render_template('test.html', foo=y)

def y(text):
    return text

然后,在test.html中

{{ y('hi') }}

There’s a much simpler decision.

@app.route('/x')
def x():
    return render_template('test.html', foo=y)

def y(text):
    return text

Then, in test.html:

{{ y('hi') }}

有条件的Jinja2速记

问题:有条件的Jinja2速记

说我有这个:

{% if files %}
    Update
{% else %}
    Continue
{% endif %}

比方说,在PHP中,我可以写一个简写的条件语句,例如:

<?php echo $foo ? 'yes' : 'no'; ?>

有没有一种方法可以将其转换为在jinja2模板中工作:

'yes' if foo else 'no'

Say I have this:

{% if files %}
    Update
{% else %}
    Continue
{% endif %}

In PHP, say, I can write a shorthand conditional, like:

<?php echo $foo ? 'yes' : 'no'; ?>

Is there then a way I can translate this to work in a jinja2 template:

'yes' if foo else 'no'

回答 0

是的,可以使用内联if-expressions

{{ 'Update' if files else 'Continue' }}

Yes, it’s possible to use inline if-expressions:

{{ 'Update' if files else 'Continue' }}

回答 1

另一种方法(但这不是python样式。它是JS样式)

{{ files and 'Update' or 'Continue' }}

Alternative way (but it’s not python style. It’s JS style)

{{ files and 'Update' or 'Continue' }}

如何在Jinja2中格式化日期?

问题:如何在Jinja2中格式化日期?

使用Jinja2,如何格式化日期字段?我知道在Python中我可以简单地做到这一点:

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

但是,如何在Jinja2中格式化日期?

Using Jinja2, how do I format a date field? I know in Python I can simply do this:

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

But how do I format the date in Jinja2?


回答 0

有两种方法可以做到这一点。直接的方法是简单地调用(并打印)模板中的strftime()方法,例如

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

另一种明显更好的方法是定义自己的过滤器,例如:

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)

(出于与i18n有关的原因,此过滤器基于babel,但您也可以使用strftime)。过滤器的优点是,您可以编写

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

看起来更好,更易于维护。另一个常见的过滤器也是“ timedelta”过滤器,其计算结果类似于“ 8分钟前编写”。您可以使用babel.dates.format_timedelta它,并将其注册为类似于此处给出的datetime示例的过滤器。

There are two ways to do it. The direct approach would be to simply call (and print) the strftime() method in your template, for example

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

Another, sightly better approach would be to define your own filter, e.g.:

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)

(This filter is based on babel for reasons regarding i18n, but you can use strftime too). The advantage of the filter is, that you can write

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

which looks nicer and is more maintainable. Another common filter is also the “timedelta” filter, which evaluates to something like “written 8 minutes ago”. You can use babel.dates.format_timedelta for that, and register it as filter similar to the datetime example given here.


回答 1

这是我在Jinja2和Flask中用于strftime的过滤器

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

然后使用过滤器,如下所示:

{{car.date_of_manufacture|strftime}}

Here’s the filter that I ended up using for strftime in Jinja2 and 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) 

And then you use the filter like so:

{{car.date_of_manufacture|strftime}}

回答 2

我认为您必须为此编写自己的过滤器。它实际上是文档中自定义过滤器的示例:http : //jinja.pocoo.org/docs/api/#custom-filters

I think you have to write your own filter for that. It’s actually the example for custom filters in the documentation: http://jinja.pocoo.org/docs/api/#custom-filters


回答 3

如果您要处理较低级别的时间对象(我经常只使用整数),而又不想出于任何原因编写自定义过滤器,则我使用的一种方法是将strftime函数作为变量传递给模板,其中可以在您需要的地方调用它。

例如:

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

然后可以在其中使用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>

If you are dealing with a lower level time object (I often just use integers), and don’t want to write a custom filter for whatever reason, an approach I use is to pass the strftime function into the template as a variable, where it can be called where you need it.

For example:

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

Which can then be used within 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>

回答 4

您可以在没有任何过滤器的模板中像这样使用它

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

You can use it like this in template without any filters

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

回答 5

Google App Engine用户:如果您是从Django转到Jinja2,并希望替换日期过滤器,请注意%格式代码是不同的。

strftime%代码在此处:http : //docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior

Google App Engine users : If you’re moving from Django to Jinja2, and looking to replace the date filter, note that the % formatting codes are different.

The strftime % codes are here: http://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior


回答 6

在烧瓶中,用通天塔,我喜欢这样做:

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

在模板中使用 {{mydatetimeobject|dt}}

因此,与babel配合使用时,您可以在messages.po中指定各种格式,例如:

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

in flask, with babel, I like to do this :

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

used in the template with {{mydatetimeobject|dt}}

so no with babel you can specify your various format in messages.po like this for instance :

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

回答 7

有一个jinja2扩展名可以使用,只需要pip安装即可(https://github.com/hackebrot/jinja2-tim

There is a jinja2 extension you can use just need pip install (https://github.com/hackebrot/jinja2-time)


在Jinja中设置变量

问题:在Jinja中设置变量

我想知道如何在Jinja中使用另一个变量设置变量。我会解释,我有一个子菜单,我想显示哪个链接处于活动状态。我尝试了这个:

{% set active_link = {{recordtype}} -%}

其中recordtype是为我的模板提供的变量。

I would like to know how can I set a variable with another variable in jinja. I will explain, I have got a submenu and I would like show which link is active. I tried this:

{% set active_link = {{recordtype}} -%}

where recordtype is a variable given for my template.


回答 0

{{ }}告诉模板打印值,这在您尝试执行的表达式中将不起作用。而是使用{% set %}template标记,然后以与普通python代码相同的方式分配值。

{% set testing = 'it worked' %}
{% set another = testing %}
{{ another }}

结果:

it worked

{{ }} tells the template to print the value, this won’t work in expressions like you’re trying to do. Instead, use the {% set %} template tag and then assign the value the same way you would in normal python code.

{% set testing = 'it worked' %}
{% set another = testing %}
{{ another }}

Result:

it worked

回答 1

多个变量分配的不错简写

{% set label_cls, field_cls = "col-md-7", "col-md-3" %}

Nice shorthand for Multiple variable assignments

{% set label_cls, field_cls = "col-md-7", "col-md-3" %}

回答 2

像这样设置

{% set active_link = recordtype -%}

Just Set it up like this

{% set active_link = recordtype -%}

获取Jinja2模板中列表的长度

问题:获取Jinja2模板中列表的长度

如何获得jinja2模板中列表中的元素数?

例如,在Python中:

print(template.render(products=[???]))

和在jinja2

<span>You have {{what goes here?}} products</span>

How do I get the number of elements in a list in jinja2 template?

For example, in Python:

print(template.render(products=[???]))

and in jinja2

<span>You have {{what goes here?}} products</span>

回答 0

<span>You have {{products|length}} products</span>

您也可以在以下表达式中使用此语法

{% if products|length > 1 %}

jinja2的内置过滤器记录在这里;具体来说,正如您已经发现的length(及其同义词count)记录为:

返回序列或映射的项目数。

因此,正如您所发现的,模板中的{{products|count}}(或等效{{products|length}})将给出“产品数量”(“列表长度”)

<span>You have {{products|length}} products</span>

You can also use this syntax in expressions like

{% if products|length > 1 %}

jinja2’s builtin filters are documented here; and specifically, as you’ve already found, length (and its synonym count) is documented to:

Return the number of items of a sequence or mapping.

So, again as you’ve found, {{products|count}} (or equivalently {{products|length}}) in your template will give the “number of products” (“length of list”)


回答 1

亚历克斯的评论看起来不错,但我仍然对使用范围感到困惑。在使用长度范围内的for条件时,以下对我有用。

{% for i in range(0,(nums['list_users_response']['list_users_result']['users'])| length) %}
<li>    {{ nums['list_users_response']['list_users_result']['users'][i]['user_name'] }} </li>
{% endfor %}

Alex’ comment looks good but I was still confused with using range. The following worked for me while working on a for condition using length within range.

{% for i in range(0,(nums['list_users_response']['list_users_result']['users'])| length) %}
<li>    {{ nums['list_users_response']['list_users_result']['users'][i]['user_name'] }} </li>
{% endfor %}

回答 2

我遇到了长度为None的问题,这导致内部服务器错误:TypeError:类型为’NoneType’的对象没有len()

我的解决方法是,如果object为None,则仅显示0并计算其他类型的长度,例如我的列表:

{{'0' if linked_contacts == None else linked_contacts|length}}

I’ve experienced a problem with length of None, which leads to Internal Server Error: TypeError: object of type ‘NoneType’ has no len()

My workaround is just displaying 0 if object is None and calculate length of other types, like list in my case:

{{'0' if linked_contacts == None else linked_contacts|length}}