flask(二)之Jinja2模板與Flask-WTF
01-文檔
官方文檔:http://docs.jinkan.org/docs/jinja2/
02-基本語義
Jinja2做構成的模板文件中,文本內容大致可以分成幾個種類。比如特殊文本(不進行轉義,比如HTML,XML格式的文本)、{{ }}表示的變量或者宏調用、{% %}表示邏輯控制,{# #}表示註釋,其中內容不被模板引擎轉義。
03-渲染模板
默認情況下,Flask在項目目錄中的templates子目錄中尋找模板。render_template()
from flask import Flask, render_template app = Flask(__name__) app.config.update({‘DEBUG‘: True, ‘TEMPLATES_AUTO_RELOAD‘: True, }) @app.route(‘/‘) def index(): return render_template("index.html") @app.route(‘/user/<name>‘) def user(name): return render_template(‘user.html‘, name=name) if __name__ == ‘__main__‘: app.run()
04-變量
Jinja2能識別所有類型的變量,如:列表、字典和對象。
示例:
變量過濾器:
05-控制結構—宏
{% macro render_comment(comment) %} <li>{{ comment }}</li> {% endmacro %} <ul> {% for comment in comments %} {{ render_comment(comment) }} {% endfor %} </ul>
為了重復使用宏,可以把宏保存在單獨的文件中,然後再需要使用的模板中導入:
{% import ‘macros.html‘ as macros %}<ul> {% for comment in comments %} {{ render_comment(comment) }} {% endfor %} </ul>
需要在多處重復使用的模板代碼寫入單獨的文件,再引入所有的模板中,以避免重復:
{% include ‘common.html‘ %}
06-使用Flask-Bootstrap集成Bootstrap
# 安裝 pip install flask-bootstrap
初始化方式:
from flask_bootstrap Bootstrap bootstrap = Bootstrap(app)
07-自定義錯誤頁面
最常見的錯誤代碼有兩個:404,500。使用 app.errorhandler 裝飾器為這兩個錯誤提供自定義的處理函數。
@app.errorhandler(404) def page_not_found(e): return render_template(‘404.html‘), 404 @app.errorhandler(500) def page_not_found(e): return render_template(‘500.html‘), 500
模板的編寫-404、500
template/base.html的內容,繼承了bootstrap/base.html的新模板。通過繼承 template/base.html 模板編寫自定義的404錯誤頁面就簡單了。
# template/404.html {% extends ‘‘base.html %} {% block title %}Flasky - Page Not Found{% endblock %} {% block page_content %} <div class="page-header"> <h1>Not Found</h1> </div> {% endblock %}
08-靜態文件
默認設置下,Flask在應用根目錄中名為static的子目錄中,尋找靜態文件。
url_for(‘static‘, filename=‘favicon.ico‘)
09-使用Flask-Moment 本地化日期和時間
# 安裝 pip install flask-moment
初始化
from flask_moment import Moment moment = Moment(app)
templates/base.html 引用 Moment.js庫
{% block script %}
{{ super }}
{{ moment.include_moment() }}
{% endblock %}
templates/index.html:使用Flask-Moment渲染時間戳
<p>The local date and time is {{ moment(current_time).format(‘LLL‘) }}.</p> <p>That was {{ moment(current_time).fromNow(refresh=True) }}</p>
fromNow()渲染相對時間戳,會自動刷新時間,最開始顯示為 "a few seconds ago",但設定refresh=True其內容會隨著時間的推移而更新。
10-Web表單 Flask-WTF
# 安裝 pip install flask-wtf
配置Flask-WTF
app = Flask(__name__) app.config[‘SECRET_KEY‘] = ‘hard to guess string‘
Falsk-WTF配置一個密鑰,是為了防止表單遭到跨站請求偽造(CSRF)攻擊。
11-簡單驗證
from flask import Flask,request,render_template from wtforms import Form,StringField from wtforms.validators import Length,EqualTo app = Flask(__name__) class RegistForm(Form): username = StringField(validators=[Length(min=3,max=10,message=‘用戶名必須在3到10位之間‘)]) password = StringField(validators=[Length(min=6,max=10,message=‘密碼必須6到10位之間‘)]) password_repeat = StringField(validators=[Length(min=6,max=10), EqualTo("password",message=‘密碼不一致‘)]) @app.route(‘/‘) def hello_world(): return ‘Hello World!‘ @app.route(‘/regist/‘,methods=[‘GET‘,‘POST‘]) def regist(): if request.method == ‘GET‘: return render_template(‘regist.html‘) else: form = RegistForm(request.form) if form.validate(): return ‘success‘ else: print(form.errors) return ‘fail‘ if __name__ == ‘__main__‘: app.run()
from wtforms import Form,StringField,IntegerField from wtforms.validators import Length,EqualTo,Email,InputRequired,NumberRange from wtforms.validators import Regexp,URL,ValidationError class LoginForm(Form): email = StringField(validators=[Email(message=‘郵箱格式不正確‘)]) username = StringField(validators=[InputRequired(message=‘這個字段必須要填‘)]) age = IntegerField(validators=[NumberRange(min=18,max=100)]) phone = StringField(validators=[Regexp(r‘1[38745]\d{9}‘)]) homepage = StringField(validators=[URL()]) captcha = StringField(validators=[Length(4,4)]) # 自定義驗證器 def validate_captcha(self,field): if field.data != ‘1234‘: #field.data:用戶提交過來的數據 raise ValidationError(‘驗證碼錯誤‘) #如果驗證失敗,就拋出驗證失敗的異常
12-使用wtfforms渲染模板
forms.py
class SettingsForm(Form): username = StringField(label="用戶名:",validators=[InputRequired(message=‘這個字段必須要填‘)]) age = IntegerField(‘年齡:‘,validators=[NumberRange(min=18, max=100)]) remeber = BooleanField(‘記住我‘) tags = SelectField(‘標簽‘,choices=[(1,‘python‘),(2,‘django‘)])
views.py
@app.route(‘/settings/‘,methods=[‘GET‘,‘POST‘]) def settings(): if request.method == ‘GET‘: form = SettingsForm() return render_template(‘settings.html‘,form=form) else: pass
template.html
<form action="" method="post"> {# 括號裏面可以添加樣式#} <p>{{ form.username.label }} {{ form.username(class="") }}</p> <p>{{ form.age.label }} {{ form.age() }}</p> <p>{{ form.remeber.label }} {{ form.remeber() }}</p> <p>{{ form.tags.label }} {{ form.tags() }}</p> <p><input type="submit" value="提交"></p> </form>
13-在視圖函數中處理表單
在視圖函數index()有兩個任務:一是渲染表單,二是接收用戶在表單中填寫的數據。
@app.route(‘/‘, methods=[‘GET‘, ‘POST‘]) def index(): name = None form = NameForm() if form.validate_on_submit(): name = form.name.data form.name.data = ‘‘ return render_template(‘index.html‘, form=form, name=name)
如果沒有指定methods參數,則視圖函數只為GET請求處理程序。
14-閃現消息
from flask import Flask, flash, render_template, redirect, url_for, session @app.route(‘/‘, methods=[‘GET‘, ‘POST‘]) def index(): form = NameForm() if form.validate_on_submit(): old_name = session.get(‘name‘) if old_name is not None and old_name != form.name.data: flash(‘Looks like you have changed your name!‘) session[‘name‘] = form.name.data return redirect(url_for(‘index‘)) return redirect(‘index.html‘, form=form, name=session.get(‘name‘))
調用flash()函數,在發給客戶端的下一個響應中顯示一個消息。get_flashed_messages()函數來開放給模板,用於獲取並渲染閃現消息。
flask(二)之Jinja2模板與Flask-WTF