Maison >développement back-end >Tutoriel Python >Moteur de modèle Jinja2 dans le framework Flask de Python

Moteur de modèle Jinja2 dans le framework Flask de Python

高洛峰
高洛峰original
2017-03-01 13:43:111717parcourir

La fonction de modèle de Flask est basée sur le moteur de modèle Jinja2. Les fichiers modèles sont stockés dans le sous-répertoire actuel des modèles (assurez-vous d'utiliser ce nom).

le code main.py est le suivant :

from flask import Flask, render_template
 
app = Flask(__name__)
 
@app.route('/hello')
@app.route(&#39;/hello/<name>&#39;)
def hello(name=None):
  return render_template(&#39;hello.html&#39;, name=name)
 
 
if __name__ == &#39;__main__&#39;:
  app.run(debug=True)

le code bonjour.html est le suivant :

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Hello Sample</title>
</head>
<body>
{% if name %}
  <h1>Hello {{ name }} !</h1>
{% else %}
  <h1>Hello World!</h1>
{% endif %}
 
</body>
</html>

Les expressions de modèle sont toutes incluses dans le délimiteur "{{ }}" ; les instructions de contrôle sont toutes incluses dans le délimiteur "{% %}" ; De plus, le modèle prend également en charge les commentaires, qui sont inclus dans le délimiteur "{# #}", et prend en charge les commentaires en bloc.
Expression

Il existe généralement plusieurs types d'expressions :

  • Les plus couramment utilisées sont les variables, qui sont transmises lors du rendu de Flask le modèle. , tel que "name" dans l'exemple ci-dessus

  • peut également être n'importe quel type Python de base, tel que la chaîne {{ "Bonjour" }}, entre guillemets ; ou une valeur numérique, Liste, tuple, dictionnaire, booléen. Cela n'a aucun sens d'afficher directement le type de base. Généralement, l'opération

  • est utilisée avec d'autres expressions. Y compris les opérations arithmétiques, telles que {{ 2 3 }} ; les opérations de comparaison, telles que {{ 2 > 1 }} ; les opérations logiques, telles que {{ False et True }}

  • filtre "|" et testeur "is". Cela sera introduit plus tard

  • appels de fonction, tels que {{ current_time() }} ; opérations d'indice de tableau, telles que {{ arr[1] }}

  • Opérateur "in", tel que {{ 1 in [1,2,3] }}

  • Opérateur de concaténation de chaînes "~", la fonction est la même comme en Python ” ” identique à {{ “Bonjour ” ~ name ~ “!” }}

  • mot-clé « if », tel que {{ 'Salut, %s' % name if nom } }. Le « si » ici n’est pas une instruction de contrôle conditionnelle.

Instructions de contrôle

Les instructions de contrôle de Jinja2 sont principalement l'instruction de contrôle conditionnelle if et l'instruction de contrôle de boucle pour. Python. Nous pouvons modifier le code du modèle dans la section précédente :

{% if name and name == &#39;admin&#39; %}
  <h1>This is admin console</h1>
{% elif name %}
  <h1>Welcome {{ name }}!</h1>
{% else %}
  <h1>Please login</h1>
{% endif %}

Ce qui précède est un exemple d'instruction de contrôle conditionnelle. Notez que l'instruction de contrôle if doit. utilisez "{% endif %}" pour terminer. Dans le modèle, vous ne pouvez pas compter sur l'indentation pour déterminer la fin du bloc de code comme vous le pouvez dans le code. Regardons à nouveau un exemple de boucle. Modifions d'abord la fonction "hello" dans le code Python et laissons-la transmettre deux listes dans le modèle.

def hello(name=None):
  return render_template(&#39;hello.html&#39;, name=name, digits=[1,2,3,4,5],
              users=[{&#39;name&#39;:&#39;John&#39;},
                 {&#39;name&#39;:&#39;Tom&#39;, &#39;hidden&#39;:True},
                 {&#39;name&#39;:&#39;Lisa&#39;}
                 {&#39;name&#39;:&#39;Bob&#39;}])

Le modèle est le suivant :

{% if name and name == &#39;admin&#39; %}
  <h1>Helle admin</h1>
{% elif name %}
  <h1>"Hello" ~ {{ name }} ~ "!"</h1>
{% else %}
  <h1>Hello World!</h1>
{% endif %}
 
  {% for digit in digits %}
  {{ digit }}
  {% endfor %}

Identique à instruction if, l'instruction de contrôle for doit se terminer par "{% endfor %}". Sur la page, il y aura des espaces entre chaque élément. Si vous ne voulez pas d'espaces, ajoutez un signe "-" à la fin de l'instruction "for" et au début de l'instruction "endfor". Par exemple :

 {% for digit in digits -%}
  {{ digit }}
 {%- endfor %}

Vous pouvez voir que le numéro "12345" est affiché ensemble. Regardons à nouveau un exemple de boucle complexe :

<dl>
  {% for user in users if not user.hidden %}
  {% if loop.first %}
  <p>User List:</p>
  {% endif %}
  <p class="{{ loop.cycle(&#39;odd&#39;, &#39;even&#39;) }}">
  <dt>User No. {{ loop.index }}</dt>
  <dd>{{ user.name }}</dd>
  </p>
  {% if loop.last %}
  <dir>Total Users: {{ loop.length }}</dir>
  {% endif %}
  {% else %}
  <li>No users found</li>
  {% endfor %}
</dl>

Il y a trois points de connaissance ici. Tout d'abord, la boucle for prend en charge l'instruction else Lorsque la liste "utilisateurs" à parcourir est vide ou None, l'instruction else est saisie.
Deuxièmement, utilisez le mot-clé if après l'instruction for pour filtrer les éléments de la boucle. Dans cet exemple, tous les utilisateurs dont l'attribut masqué est True seront filtrés.
De plus, les variables de boucle intégrées de Jinja2 sont accessibles dans la boucle for. Dans cet exemple, nous afficherons le titre avant le premier élément, le nombre total après le dernier élément et le numéro de série de chaque élément. De plus, les éléments HTML p pour les éléments pairs et impairs auront des classes différentes. Si nous ajoutons le style CSS suivant, nous pouvons voir le passage piéton.

<style type="text/css">
  .odd {
    background-color: #BDF;
  }
</style>

Les variables intégrées à la boucle de Jinja2 incluent principalement les éléments suivants :


1

2

3

4

5

6

7

8

9

10

11

12


de flacon importation Flacon, render_template

app = Flacon(__nom__)

@application.itinéraire('/bonjour')

@app.itinéraire(' /bonjour/ac64eef71da29b3103d7dea589cbf495')

def bonjour(nom=Aucun) :

    retour render_template('hello.html', nom=nom)

 

 

si __name__ == '__main__' :

    application.exécuter(débogage=Vrai)


另外,如果你启用了”jinja2.ext.loopcontrols”扩展的话,你还可以在循环中使用”{% break %}”和”{% continue %}”来控制循环执行。
其它常用语句:

忽略模板语法

有时候,我们在页面上就是要显示”{{ }}”这样的符号怎么办?Jinja2提供了”raw”语句来忽略所有模板语法。

{% raw %}
  <ul>
  {% for item in items %}
    <li>{{ item }}</li>
  {% endfor %}
  </ul>
{% endraw %}

自动转义

我们将本文一开始的Flask代码”hello()”方法改动下:

@app.route(&#39;/hello&#39;)
@app.route(&#39;/hello/<name>&#39;)
def hello(name=None):
  if name is None:
    name = &#39;<em>World</em>&#39;
  return render_template(&#39;hello.html&#39;, name=name)

此时,访问”http://www.php.cn/:5000/hello”,页面上会显示”Welcome 907fae80ddef53131f3292ee4f81644bWorldd1c6776b927dc33c5d9114750b586338!”,也就是这个HTML标签”907fae80ddef53131f3292ee4f81644b”被自动转义了。Flask会对”.html”, “.htm”, “.xml”, “.xhtml”这四种类型的模板文件开启HTML格式自动转义。这样也可以防止HTML语法注入。如果我们不想被转义怎么办?

{% autoescape false %}
 <h1>Hello {{ name }}!</h1>
{% endautoescape %}

将”autoescape”开关设为”false”即可,反之,设为”true”即开启自动转义。使用”autoescape”开关前要启用”jinja2.ext.autoescape”扩展,在Flask框架中,这个扩展默认已启用。
赋值

使用”set”关键字给变量赋值:

{% set items = [[1,2],[3,4,5]] %}

with语句

类似于Python中的”with”关键字,它可以限制with语句块内对象的作用域:

{% with foo = 1 %}
  {% set bar = 2 %}
  {{ foo + bar }}
{% endwith %}
{# foo and bar are not visible here #}

使用”with”关键字前要启用”jinja2.ext.with_”扩展,在Flask框架中,这个扩展默认已启用。
执行表达式

{% with arr = [&#39;Sunny&#39;] %}
 {{ arr.append(&#39;Rainy&#39;) }}
 {{ arr }}
{% endwith %}

看上面这段代码,我们想执行列表的”append”操作,这时使用”{{ arr.append(‘Rainy') }}”页面会输出”None”,换成”{% %}”来执行,程序会报错,因为这是个表达式,不是语句。那怎么办?我们可以启用”jinja2.ext.do”扩展。然后在模板中执行”do”语句即可:

{% with arr = [&#39;Sunny&#39;] %}
 {% do arr.append(&#39;Rainy&#39;) %}
 {{ arr }}
{% endwith %}

上下文环境
Flask每个请求都有生命周期,在生命周期内请求有其上下文环境Request Context。作为在请求中渲染的模板,自然也在请求的生命周期内,所以Flask应用中的模板可以使用到请求上下文中的环境变量,及一些辅助函数。本文就会介绍下这些变量和函数。
标准上下文变量和函数

请求对象request
request对象可以用来获取请求的方法”request.method”,表单”request.form”,请求的参数”request.args”,请求地址”request.url”等。它本身是一个字典。在模板中,你一样可以获取这些内容,只要用表达式符号”{{ }}”括起来即可。

<p>{{ request.url }}</p>

在没有请求上下文的环境中,这个对象不可用。
会话对象session
session对象可以用来获取当前会话中保存的状态,它本身是一个字典。在模板中,你可以用表达式符号”{{ }}”来获取这个对象。
Flask代码如下,别忘了设置会话密钥哦:

@app.route(&#39;/&#39;)
def index():
  session[&#39;user&#39;] = &#39;guest&#39;
  return render_template(&#39;hello.html&#39;)
 
app.secret_key = &#39;123456&#39;

模板代码:

<p>User: {{ session.user }}</p>

在没有请求上下文的环境中,这个对象不可用。
全局对象g
全局变量g,用来保存请求中会用到全局内容,比如数据库连接。模板中也可以访问。
Flask代码:

@app.route(&#39;/&#39;)
def index():
  g.db = &#39;mysql&#39;
  return render_template(&#39;hello.html&#39;)

模板代码:

<p>DB: {{ g.db }}</p>

g对象是保存在应用上下文环境中的,也只在一个请求生命周期内有效。在没有应用上下文的环境中,这个对象不可用。
Flask配置对象config
导入的配置信息,就保存在”app.config”对象中。这个配置对象在模板中也可以访问。

 <p>Host: {{ config.DEBUG }}</p>

“config”是全局对象,离开了请求生命周期也可以访问。
url_for()函数
url_for()函数可以用来快速获取及构建URL,Flask也将此函数引入到了模板中,比如下面的代码,就可以获取静态目录下的”style.css”文件。

<link rel="stylesheet" href="{{ url_for(&#39;static&#39;, filename=&#39;style.css&#39;) }}">

该函数是全局的,离开了请求生命周期也可以调用。
get_flashed_messages()函数
get_flashed_messages()函数是用来获取消息闪现的。这也是一个全局可使用的函数。
自定义上下文变量和函数

自定义变量
除了Flask提供的标准上下文变量和函数,我们还可以自己定义。下面我们就来先定义一个上下文变量,在Flask应用代码中,加入下面的函数:

from flask import current_app
 
@app.context_processor
def appinfo():
  return dict(appname=current_app.name)

函数返回的是一个字典,里面有一个属性”appname”,值为当前应用的名称。我们曾经介绍过,这里的”current_app”对象是一个定义在应用上下文中的代理。函数用”@app.context_processor”装饰器修饰,它是一个上下文处理器,它的作用是在模板被渲染前运行其所修饰的函数,并将函数返回的字典导入到模板上下文环境中,与模板上下文合并。然后,在模板中”appname”就如同上节介绍的”request”, “session”一样,成为了可访问的上下文对象。我们可以在模板中将其输出:

<p>Current App is: {{ appname }}</p>

自定义函数
同理我们可以自定义上下文函数,只需将上例中返回字典的属性指向一个函数即可,下面我们就来定义一个上下文函数来获取系统当前时间:

import time
 
@app.context_processor
def get_current_time():
  def get_time(timeFormat="%b %d, %Y - %H:%M:%S"):
    return time.strftime(timeFormat)
  return dict(current_time=get_time)

我们可以试下在模板中将其输出:

<p>Current Time is: {{ current_time() }}</p>
 <p>Current Day is: {{ current_time("%Y-%m-%d") }}</p>

上下文处理器可以修饰多个函数,也就是我们可以定义多个上下文环境变量和函数。
完整实例:
flask代码:

from flask import Flask, render_template, session, g, current_app
import time
 
app = Flask(__name__)
 
@app.route(&#39;/&#39;)
def index():
  session[&#39;user&#39;] = &#39;guest&#39;
  g.db = &#39;mysql&#39;
  return render_template(&#39;hello-2.html&#39;)
 
@app.context_processor
def appinfo():
  return dict(appname=current_app.name)
 
@app.context_processor
def get_current_time():
  def get_time(timeFormat="%b %d, %Y - %H:%M:%S"):
    return time.strftime(timeFormat)
  return dict(current_time=get_time)
 
app.secret_key = &#39;123456&#39;
 
if __name__ == &#39;__main__&#39;:
  app.run(debug=True)

模板代码:


Hello Sample
<link rel="stylesheet" href="{{ url_for(&#39;static&#39;, filename=&#39;style.css&#39;) }}">
 

Hello World!

Request URL: {{ request.url }}

<p>User: {{ session.user }}</p> <p>DB: {{ g.db }}</p> <p>Host: {{ config.DEBUG }}</p> <p>Current App is: {{ appname }}</p> <p>Current Time is: {{ current_time() }}</p> <p>Current Day is: {{ current_time("%Y-%m-%d") }}</p> {% with messages = get_flashed_messages() %} {% if messages %} {% for message in messages %} Flash Message: {{ message }} {% endfor %} {% endif %} {% endwith %}


更多Python的Flask框架中的Jinja2模板引擎相关文章请关注PHP中文网!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn