Flask模板

模板基本語法html

{% if user %}
    {{ user }}
{% else %}
    hello!
<ul>
    {% for index in indexs %}
    <li> {{ index }} </li>
    {% endfor %}
</ul>

 

一 變量前端

在模板中{{ variable }}結構表示變量,是一種特殊的佔位符,告訴模板引擎這個位置的值,從渲染模板時使用的數據中獲取;Jinja2除了能識別基本類型的變量,還能識別{};python

視圖:git

from flask import Flask, render_template

app = Flask(__name__)


@app.route("/index")
def index():
    data = {
        "name": "test",
        "size": 11,
        "adict": {"title": "index"},
        "alist": [1,2,3,4,5,6]
    }
    return render_template('index.html', **data)
    # return render_template("index.html", name="tile")


if __name__ == '__main__':
    app.run()
View Code

模板:web

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta http-equiv='Content-type' content='text/htm'>
</head>
<body>
<p>name---{{ name }}</p>
<p>size---{{ size }}</p>
<p>adict---title:{{ adict["title"] }}</p>
<p>adict---title:{{ adict.title }}</p>
<p>alist---{{ alist }}</p>
<p>alist---:alist[0]:{{ alist[0] }}</p>
<p>alist---:alist[2]:{{ alist.2 }}</p>
<p>alist---:alist[0]+alist[1]:{{ alist[0] + alist[1] }}</p>
<p>{{ "hello" + "flask" }}</p>
</body>
</html>
View Code

自定義錯誤頁面:flask

@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404
View Code

 

二 過濾器api

過濾器的本質就是函數。有時候咱們不單單只是須要輸出變量的值,咱們還須要修改變量的顯示,甚至格式化、運算等等,這就用到了過濾器。 過濾器的使用方式爲:變量名 | 過濾器。 過濾器名寫在變量名後面,中間用 | 分隔。如:{{variable | capitalize}},這個過濾器的做用:把變量variable的值的首字母轉換爲大寫,其餘字母轉換爲小寫。 其餘經常使用過濾器以下:服務器

2.1 字符串過濾器:cookie

safe:禁用轉義; <p>{{ '<em>hello</em>' | safe }}</p> capitalize:把變量值的首字母轉成大寫,其他字母轉小寫; <p>{{ 'hello' | capitalize }}</p> lower:把值轉成小寫; <p>{{ 'HELLO' | lower }}</p> upper:把值轉成大寫; <p>{{ 'hello' | upper }}</p> title:把值中的每一個單詞的首字母都轉成大寫; <p>{{ 'hello' | title }}</p> trim:把值的首尾空格去掉; <p>{{ ' hello world ' | trim }}</p> reverse:字符串反轉; <p>{{ 'olleh' | reverse }}</p> format:格式化輸出; <p>{{ '%s is %d' | format('name',17) }}</p> striptags:渲染以前把值中全部的HTML標籤都刪掉; <p>{{ '<em>hello</em>' | striptags }}</p>

2.2 支持鏈式使用過濾器session

<p>{{ 「 hello world  「 | trim | upper }}</p>

2.3 列表過濾器

first:取第一個元素 <p>{{ [1,2,3,4,5,6] | first }}</p> last:取最後一個元素 <p>{{ [1,2,3,4,5,6] | last }}</p> length:獲取列表長度 <p>{{ [1,2,3,4,5,6] | length }}</p> sum:列表求和 <p>{{ [1,2,3,4,5,6] | sum }}</p> sort:列表排序 <p>{{ [6,2,3,1,5,4] | sort }}</p>

2.4 語句塊過濾

{% filter upper %}
    this is a Flask Jinja2 introduction
  {% endfilter %}

2.5 自定義過濾器:

過濾器的本質是函數。當模板內置的過濾器不能知足需求,能夠自定義過濾器。自定義過濾器有兩種實現方式:一種是經過Flask應用對象的add_template_filter方法。還能夠經過裝飾器來實現自定義過濾器。

自定義的過濾器名稱若是和內置的過濾器重名,會覆蓋內置的過濾器。

實現方式一:經過調用應用程序實例的add_template_filter方法實現自定義過濾器。該方法第一個參數是函數名,第二個參數是自定義的過濾器名稱。

def list_step_2(li):
    """自定義過濾器"""
    return li[::2]

# 註冊過濾器
app.add_template_filter(list_step_2, "li2")
View Code

實現方式二:用裝飾器來實現自定義過濾器。裝飾器傳入的參數是自定義的過濾器名稱。

@app.template_filter("li3")
def list_step_3(li):
    """自定義過濾器"""
    return li[::3]
View Code

 

三 Web表單:

web表單是web應用程序的基本功能。

它是HTML頁面中負責數據採集的部件。表單有三個部分組成:表單標籤、表單域、表單按鈕。表單容許用戶輸入數據,負責HTML頁面數據採集,經過表單將用戶輸入的數據提交給服務器。

在Flask中,爲了處理web表單,咱們通常使用Flask-WTF擴展,它封裝了WTForms,而且它有驗證表單數據的功能。

WTForms支持的HTML標準字段

 

字段對象 說明
StringField 文本字段
TextAreaField 多行文本字段
PasswordField 密碼文本字段
HiddenField 隱藏文本字段
DateField 文本字段,值爲datetime.date格式
DateTimeField 文本字段,值爲datetime.datetime格式
IntegerField 文本字段,值爲整數
DecimalField 文本字段,值爲decimal.Decimal
FloatField 文本字段,值爲浮點數
BooleanField 複選框,值爲True和False
RadioField 一組單選框
SelectField 下拉列表
SelectMultipleField 下拉列表,可選擇多個值
FileField 文本上傳字段
SubmitField 表單提交按鈕
FormField 把表單做爲字段嵌入另外一個表單
FieldList 一組指定類型的字段

 

WTForms經常使用驗證函數

驗證函數 說明
DataRequired 確保字段中有數據
EqualTo 比較兩個字段的值,經常使用於比較兩次密碼輸入
Length 驗證輸入的字符串長度
NumberRange 驗證輸入的值在數字範圍內
URL 驗證URL
AnyOf 驗證輸入值在可選列表中
NoneOf 驗證輸入值不在可選列表中

 

使用Flask-WTF須要配置參數SECRET_KEY。

CSRF_ENABLED是爲了CSRF(跨站請求僞造)保護。 SECRET_KEY用來生成加密令牌,當CSRF激活的時候,該設置會根據設置的密匙生成加密令牌。

 

在HTML頁面中直接寫form表單:

#模板文件
<form method='post'>
    <input type="text" name="username" placeholder='Username'>
    <input type="password" name="password" placeholder='password'>
    <input type="submit">
</form>
View Code

視圖函數中獲取表單數據:

from flask import Flask,render_template,request

@app.route('/login',methods=['GET','POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        print username,password
    return render_template('login.html',method=request.method)
View Code

 

使用Flask-WTF實現表單。

pip install Flask-WTF

配置參數:

app.config['SECRET_KEY'] = '.........'

模板頁面:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta http-equiv='Content-type' content='text/htm'>
</head>
<body>
<form method="post">
    {{ reg_form.csrf_token }}
{{ reg_form.username.label }}
<p>{{ reg_form.username }}</p>
{{ reg_form.username.errors.0 }}

{{ reg_form.password.label }}
<p>{{ reg_form.password }}</p>
{{ reg_form.password.errors.0 }}

{{ reg_form.repassword.label }}
<p>{{ reg_form.repassword }}</p>
{{ reg_form.repassword.errors.0 }}
<br>
{{ reg_form.submit }}
</form>

</body>
</html>
View Code

視圖函數:

from flask import Flask, render_template, url_for, redirect, session
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, EqualTo
app = Flask(__name__)

app.config["SECRET_KEY"] = "ada898u2q11joloadad02"

class RegiterForm(FlaskForm):
    username = StringField(label="用戶名", validators=[DataRequired("用戶名不能爲空")])
    password = PasswordField(label="密碼", validators=[DataRequired("密碼不能爲空")])
    repassword = PasswordField(label="確認密碼", validators=[DataRequired("確認密碼不能爲空"), EqualTo("password", "兩次密碼輸入不一致")])
    submit = SubmitField(label="提交")


@app.route("/register", methods=['GET', "POST"])
def register():
    # 建立表單對象, 若是是post請求, 前端發送了數據,flask會把數據在構造form對象的數據,存在對象中
    reg_form = RegiterForm()

    # 判斷form中的數據是否合法
    if reg_form.validate_on_submit():
        username = reg_form.username.data
        password = reg_form.password.data
        repassword = reg_form.repassword.data

        session["username"] = username

        print(username, password, repassword)
        return redirect(url_for("index"))
    return render_template('register.html', reg_form=reg_form)


@app.route("/index")
def index():
    username = session.get("username")
    return "hello %s " % username


if __name__ == '__main__':
    app.run()
View Code

 

四 控制語句

4.1 if控制語句

@app.route('/user')
def user():
    user = 'wusong'
    return render_template('user.html',user=user)
View Code
 <html>
 <head>
     {% if user %}
        <title> hello {{user}} </title>
    {% else %}
         <title> welcome to flask </title>        
    {% endif %}
 </head>
 <body>
     <h1>hello world</h1>
 </body>
 </html>
View Code

 

4.2 for循環語句

 @app.route('/loop')
 def loop():
    fruit = ['apple','orange','pear','grape']
    return render_template('loop.html',fruit=fruit)
View Code
<html>
 <head>
     {% if user %}
        <title> hello {{user}} </title>
    {% else %}
         <title> welcome to flask </title>        
    {% endif %}
 </head>
 <body>
     <h1>hello world</h1>
    <ul>
        {% for index in fruit %}
            <li>{{ index }}</li>
        {% endfor %}
    </ul>
 </body>
 </html>
View Code

 

五 宏、繼承、包含

相似於python中的函數,宏的做用就是在模板中重複利用代碼,避免代碼冗餘。

Jinja2支持宏,還能夠導入宏,須要在多處重複使用的模板代碼片斷能夠寫入單獨的文件,再包含在全部模板中,以免重複。

5.1 宏

定義宏

{% macro input() %}
<input type="text" name="username" value="">
{% endmacro %}

調用宏

{{ input() }}

定義帶參數的宏

{% macro input1(name, value="", type="text") %}
<input type="{{ type }}" name="{{ name }}" value="{{ value }}">
{% endmacro %}

調用宏,並傳遞參數

{{ input1(pwd, type="password") }}

把宏單獨抽取出來,封裝成html文件,其它模板中導入使用

文件名能夠自定義macro_input.html

{% macro function() %}

    <input type="text" name="username" placeholde="Username">
    <input type="password" name="password" placeholde="Password">
    <input type="submit">
{% endmacro %}

在其它模板文件中先導入,再調用

{% import 'macro_input.html' as func %}
{{ func.function() }}

 

5.2模板繼承

模板繼承是爲了重用模板中的公共內容。通常Web開發中,繼承主要使用在網站的頂部菜單、底部。這些內容能夠定義在父模板中,子模板直接繼承,而不須要重複書寫。

{% block top %}.......{% endblock %}標籤訂義的內容,至關於在父模板中挖個坑,當子模板繼承父模板時,能夠進行填充。

父模板:base.html

{% block top %}
    頂部菜單
  {% endblock top %}

  {% block content %}
  {% endblock content %}

  {% block bottom %}
    底部
  {% endblock bottom %}

子模板:

{% extends 'base.html' %}
  {% block content %}
   須要填充的內容
  {% endblock content %}

模板繼承使用時注意點:

  • 不支持多繼承。

  • 爲了便於閱讀,在子模板中使用extends時,儘可能寫在模板的第一行。

  • 不能在一個模板文件中定義多個相同名字的block標籤。

  • 當在頁面中使用多個block標籤時,建議給結束標籤起個名字,當多個block嵌套時,閱讀性更好。

 

5.3包含(Include)

Jinja2模板中,除了宏和繼承,還支持一種代碼重用的功能,叫包含(Include)。它的功能是將另外一個模板整個加載到當前模板中,並直接渲染。

示例:

include的使用

{% include 'hello.html' %}

包含在使用時,若是包含的模板文件不存在時,程序會拋出TemplateNotFound異常,能夠加上ignore missing關鍵字。若是包含的模板文件不存在,會忽略這條include語句。

示例:

include的使用加上關鍵字ignore missing

{% include 'hello.html' ignore missing %}
  • 宏、繼承、包含:
    • 宏(Macro)、繼承(Block)、包含(include)均能實現代碼的複用。

    • 繼承(Block)的本質是代碼替換,通常用來實現多個頁面中重複不變的區域。

    • 宏(Macro)的功能相似函數,能夠傳入參數,須要定義、調用。

    • 包含(include)是直接將目標模板文件整個渲染出來。

 

六 Flask中的特殊變量和方法

在Flask中,有一些特殊的變量和方法是能夠在模板文件中直接訪問的。

config 對象:

config 對象就是Flask的config對象,也就是 app.config 對象。

{{ config.SQLALCHEMY_DATABASE_URI }}

request 對象:

就是 Flask 中表示當前請求的 request 對象,request對象中保存了一次HTTP請求的一切信息。

request經常使用的屬性以下:

屬性 說明 類型
data 記錄請求的數據,並轉換爲字符串 *
form 記錄請求中的表單數據 MultiDict
args 記錄請求中的查詢參數 MultiDict
cookies 記錄請求中的cookie信息 Dict
headers 記錄請求中的報文頭 EnvironHeaders
method 記錄請求使用的HTTP方法 GET/POST
url 記錄請求的URL地址 string
files 記錄請求上傳的文件 *

 

{{ request.url }}

url_for 方法:

url_for() 會返回傳入的路由函數對應的URL,所謂路由函數就是被 app.route() 路由裝飾器裝飾的函數。若是咱們定義的路由函數是帶有參數的,則能夠將這些參數做爲命名參數傳入。

{{ url_for('index') }}

{{ url_for('post', post_id=1024) }}

get_flashed_messages方法:

返回以前在Flask中經過 flash() 傳入的信息列表。把字符串對象表示的消息加入到一個消息隊列中,而後經過調用 get_flashed_messages() 方法取出。

{% for message in get_flashed_messages() %}
    {{ message }}
{% endfor %}

示例:

from flask import Flask, render_template, flash

app = Flask(__name__)

app.config["SECRET_KEY"] = "diaj29u912kjwsle01sda"

flag = True

@app.route("/index")
def index():
    global flag
    if flag:
        flash("flash1")
        flash("flash2")
        flash("flash3")
        flag = False
    return render_template("index.html")


if __name__ == '__main__':
    app.run()
View Code
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta http-equiv='Content-type' content='text/htm'>
</head>
<body>
<h1>閃現</h1>
{% for msg in get_flashed_messages() %}
{{ msg }}
{% endfor %}

</body>
</html>
View Code
相關文章
相關標籤/搜索