Flask 學習(二)jinja2模板介紹

控制語句和表達式

舉例html

Flask Python代碼json

from flask import Flask, render_template, redirect, request

app = Flask(__name__)

STUDENT = {'name': 'Old', 'age': 38, 'gender': ''}

STUDENT_LIST = [
    {'name': 'Old', 'age': 38, 'gender': ''},
    {'name': 'Boy', 'age': 73, 'gender': ''},
    {'name': 'EDU', 'age': 84, 'gender': ''}
]

STUDENT_DICT = {
    'a': {'name': 'Old', 'age': 38, 'gender': ''},
    'b': {'name': 'Boy', 'age': 73, 'gender': ''},
    'c': {'name': 'EDU', 'age': 84, 'gender': ''},
}

@app.route("/detail")
def detail():
    print(url_for("detail"))
    return render_template("detail.html", **STUDENT)

@app.route("/detail_list", )
def detail_list():
    return render_template("detail_list.html", stu_list=STUDENT_LIST)

@app.route("/detail_dict")
def detail_dict():
    return render_template("detail_dict.html", stu_dict=STUDENT_DICT)
detail.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<body>
{{ stu }}
<table border="1px">
    <tr>
        <td>name</td>
        <td>age</td>
        <td>gender</td>
    </tr>
    <tr>
        <td>{{ name }}</td>
        <td>{{ age }}</td>
        <td>{{ gender }}</td>
    </tr>
</table>
</body>
</html>
detail_list.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<body>
{{ stu_list }}
<table border="1px">
    <tr>
        <td>name</td>
        <td>age</td>
        <td>gender</td>
    </tr>
      {% for stu in stu_list %}
        {% if stu.name != "Old" %}
            {% if stu.age != 73 %}
                <tr>
                    <td>{{ stu.name }}</td>
                    <td>{{ stu.get("age") }}</td>
                    <td>{{ stu["gender"] }}</td>
                </tr>
            {% endif %}
        {% endif %}
    {% endfor %}
</table>
</body>
</html>
detail_dict.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<body>
{{ stu_dict }}
<table border="1px">
    <tr>
        <td>id</td>
        <td>name</td>
        <td>age</td>
        <td>gender</td>
    </tr>
    {% for stu_key,stu_value in stu_dict.items() %}
        <tr>
            <td>{{ stu_key }}</td>
            <td>{{ stu_value.get("name") }}</td>
            <td>{{ stu_value.age }}</td>
            <td>{{ stu_value.gender }}</td>
        </tr>
    {% endfor %}
</table>
</body>
</html>

表達式

1.最經常使用的是變量,由Flask渲染模板時傳過來,好比name
也能夠是任意一種Python基礎類型,好比字符串{{stu_list}},用引號括起;或者數值,列表,元祖,字典,布爾值。直接顯示基礎類型沒啥意義,通常配合其餘表達式一塊兒用
2.運算。包括算數運算,如{{ 2 + 3 }};比較運算,如{{ 2 > 1 }};邏輯運算,如{{ False and True }}
3.過濾器|和測試器is
4.函數調用,如{{ current_time() }};數組下標操做,如{{ arr[1] }}
in操做符,如{{ 1 in [1,2,3] }}
5.字符串鏈接符~,做用同Python中的+同樣,如{{ "Hello " ~ name ~ "!" }}

控制語句

Jinja2的控制語句主要就是條件控制語句if,和循環控制語句for,語法相似於Python
if-else:
{% if name and name == 'admin'  %}
    <h1>This is admin console</h1>
{% elif name %}
    <h1>Welcome {{ name }}!</h1>
{% else %}
    <h1>Please login</h1>
{% endif %}

for:
  {% for stu in stu_list%}
    {{ stu }}
  {% endfor %}

 過濾器

字符串

<body>
{# 當變量未定義時,顯示默認字符串,能夠縮寫爲d #}
<p>{{ name | default('No name', true) }}</p>

{# 單詞首字母大寫 #}
<p>{{ 'hello world' | capitalize }}</p>

{# 單詞全小寫 #}
<p>{{ 'XML' | lower }}</p>

{# 去除字符串先後的空白字符 #}
<p>{{ '  hello  ' | trim }}</p>

{# 字符串反轉,返回"olleh" #}
<p>{{ 'hello' | reverse }}</p>

{# 格式化輸出,返回"Number is 99" #}
<p>{{ '%s is %d' | format("Number", 99) }}</p>

{# 關閉HTML自動轉義 #}
<p>{{ '<em>name</em>' | safe }}</p>

{% autoescape false %}
{# HTML轉義,即便autoescape關了也轉義,能夠縮寫爲e #}
<p>{{ '<em>name</em>' | escape }}</p>
{% endautoescape %}

</body>

數值操做

{# 四捨五入取整,返回13.0 #}
<p>{{ 12.98 | round }}</p>

{# 向下截取到小數點後2位,返回12.88 #}
<p>{{ 12.8888 | round(2, 'floor') }}</p>

{# 絕對值,返回12 #}
<p>{{ -12 | abs }}</p>

列表操做

# 取第一個元素 #}
<p>{{ [1,2,3] | first }}</p>

{# 取最後一個元素 #}
<p>{{ [1,2,3] | last }}</p>

{# 返回列表長度,能夠寫爲count #}
<p>{{ [1,2,3,4,5] | length }}</p>

{# 列表求和 #}
<p>{{ [1,2,3,4,5] | sum }}</p>

{# 列表排序,默認爲升序 #}
<p>{{ [3,2,1,5,4] | sort }}</p>

{# 合併爲字符串,返回"1 | 2 | 3 | 4 | 5" #}
<p>{{ [1,2,3,4,5] | join(' | ') }}</p>

{# 列表中全部元素都全大寫。這裏能夠用upper,lower,但capitalize無效 #}
<p>{{ ['alex','bob','ada'] | upper }}</p>

字典

{% set users=[{'name':'Tom','gender':'M','age':20},
              {'name':'John','gender':'M','age':18},
              {'name':'Mary','gender':'F','age':24},
              {'name':'Bob','gender':'M','age':31},
              {'name':'Lisa','gender':'F','age':19}]
%}


{# 按指定字段排序,這裏設reverse爲true使其按降序排 #}
<ul>
{% for user in users | sort(attribute='age', reverse=true) %}
     <li>{{ user.name }}, {{ user.age }}</li>
{% endfor %}
</ul>

{# 列表分組,每組是一個子列表,組名就是分組項的值 #}
<ul>
{% for group in users|groupby('gender') %}
    <li>{{ group.grouper }}<ul>
    {% for user in group.list %}
        <li>{{ user.name }}</li>
    {% endfor %}</ul></li>
{% endfor %}
</ul>

{# 取字典中的某一項組成列表,再將其鏈接起來 #}
<p>{{ users | map(attribute='name') | join(', ') }}</p>

 

 

自定義過濾器

# 第一種方式
def get_even_list(l):
        return l[::2]
# 函數的第一個參數是過濾器函數,第二個參數是過濾器名稱
app.add_template_filter(get_even_list, 'even_filter')

# 第二種方式
@app.template_filter()  # 過濾器函數
def is_even(num):
    if num % 2 == 0:
        return "even number"
    else:
        return "odd number"

使用flask

<p>{{ [1,2,3,4,5] | even_filter }}</p>

<p>{{ 2 | is_even }}</p>

 

測試器

測試器老是返回一個布爾值,它能夠用來測試一個變量或者表達式,使用」is」關鍵字來進行測試。api

 {% set name='ab'  %}
{% if name is lower %}
  <h2>"{{ name }}" are all lower case.</h2>
{% endif %}

測試器本質上也是一個函數,它的第一個參數就是待測試的變量,在模板中使用時能夠省略去。若是它有第二個參數,數組

模板中就必須傳進去。測試器函數返回的必須是一個布爾值,這樣才能夠用來給if語句做判斷。app

內置測試器

舉例函數

{# 檢查變量是否被定義,也能夠用undefined檢查是否未被定義 #}
{% if name is defined %}
    <p>Name is: {{ name }}</p>
{% endif %}

{# 檢查是否全部字符都是大寫 #}
{% if name is upper %}
  <h2>"{{ name }}" are all upper case.</h2>
{% endif %}

{# 檢查變量是否爲空 #}
{% if name is none %}
  <h2>Variable is none.</h2>
{% endif %}

{# 檢查變量是否爲字符串,也能夠用number檢查是否爲數值 #}
{% if name is string %}
  <h2>{{ name }} is a string.</h2>
{% endif %}

{# 檢查數值是不是偶數,也能夠用odd檢查是否爲奇數 #}
{% if 2 is even %}
  <h2>Variable is an even number.</h2>
{% endif %}

{# 檢查變量是否可被迭代循環,也能夠用sequence檢查是不是序列 #}
{% if [1,2,3] is iterable %}
  <h2>Variable is iterable.</h2>
{% endif %}

{# 檢查變量是不是字典 #}
{% if {'name':'test'} is mapping %}
  <h2>Variable is dict.</h2>
{% endif %}

官方文檔post

https://jinja.palletsprojects.com/en/master/templates/#builtin-tests測試

自定義測試器

定義網站

# 自定義測試器
# 第一種方式
import re
def test_tel(tel_num):
    tel_re = r'\d{11}'
    return re.match(tel_re,tel_num)

app.add_template_test(test_tel,"is_tel")

# 第二種方式
@app.template_test('start_with')
def start_with(str, suffix):
    return str.lower().startswith(suffix.lower())

使用

{% set tel = '18910171111' %}
{% if tel is is_tel %}
  <h2>{{ tel }} is mobile phone</h2>
{% endif %}


 {% set name = 'Hello world' %}
{% if name is start_with 'hello' %}
  <h2>"{{ name }}" start_with "hello"</h2>
{% endif %}

 

全局函數

內置全局函數

{# 全局函數range()的做用同Python裏的同樣,返回指定範圍內的數值序列。三個參數分別是開始值,結束值(不包含),間隔。
若是隻傳兩個參數,那間隔默認爲1;若是隻傳1個參數,那開始值默認爲0。 #}
<ul>
 {% for num in range(10,20,2) %}
  <li>Number is "{{ num }}"</li>
{% endfor %}
</ul>
{# dict()函數,方便生成字典型變量 #}

{% set user = dict(name='Joh',age=22) %}
<p>{{ user | tojson | safe }}</p>

{# 顯示 '{"age": 22, "name": "Joh"}' #}

{# joiner()函數,它能夠初始化爲一個分隔符,而後第一次調用時返回空字符串,之後再調用則返回分隔符 #}
{% set sep = joiner("|") %}
{% for val in range(5) %}
    {{ sep() }} <span>{{ val }}</span>
{% endfor %}
{# 顯示 "0 | 1 | 2 | 3 | 4" #}

{# cycler()函數,在給定的序列中輪循 #}
{% set cycle = cycler('odd', 'even') %}
<ul>
{% for num in range(10, 20, 2) %}
    <li class="{{ cycle.next() }}">Number is "{{ num }}",
    next line is "{{ cycle.current }}" line.</li>
{% endfor %}
{#
next(),返回當前值,並往下一個值輪循
reset(),重置爲第一個值
current,當前輪循到的值
#}
</ul>

官方文檔

https://jinja.palletsprojects.com/en/master/templates/#list-of-global-functions

自定義全局函數

定義

# 自定義全局函數
# 第一種方式

@app.template_global()
def add_sum(*args):
    return sum(args)

# 第二種方式
import time
def current_time(timeFormat="%b %d, %Y - %H:%M:%S"):
    return time.strftime(timeFormat)

app.add_template_global(current_time, 'current_time')

使用

<p>{{ add_sum(1,2,3,4,5) }}</p>
<p>Current Time is: {{ current_time() }}</p>
<p>Current Day is: {{ current_time("%Y-%m-%d") }}</p>

 

塊 (Block)

通常咱們的網站雖然頁面多,可是不少部分是重用的,好比頁首,頁腳,導航欄之類的。對於每一個頁面,都要寫這些代碼,很麻煩。

Flask的Jinja2模板支持模板繼承功能,省去了這些重複代碼。

template:

<body>
你好,template1
{% block template1 %}

{% endblock %}
你好,template2
{% block template2 %}

{% endblock %}
你好,template
{% block template %}

{% endblock %}
</body>

extend:

{% extends "he.html" %}

{% block template %}
    <h1>yuan</h1>
{% endblock %}

{% block template1 %}
    <h1>alex</h1>
{% endblock %}

{% block template2 %}
    <h1>wu</h1>
    {% include "aaa.html" %}
{% endblock %}
相關文章
相關標籤/搜索