Date: Mar. 3rd, 2019
Lecturer: Chia
$ mkdir webform
$ cd webform
$ python -m venv venv
$ venv\Scripts\activate
(venv) $ pip install flask
開啟虛擬環境
hello.py初始化
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return '<h1>Hello World!</h1>'
(venv) $ set FLASK_APP=hello.py
(venv) $ set FLASK_DEBUG=1
(venv) $ flask run
執行Flask
安裝擴充套件:Flask-WTF
(venv) $ pip install flask-wtf
Basic HTML Form
在app組態設置密鑰(secret key):
from flask import Flask
app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired
class NameForm(FlaskForm):
name = StringField('What is your name?', validators=[DataRequired()])
submit = SubmitField('Submit')
在app定義表單類別:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Web Form</title>
</head>
<body>
<form method="POST">
{{ form.hidden_tag() }}
{{ form.name.label }} {{ form.name() }}
{{ form.submit() }}
</form>
</body>
</html>
轉譯表單HTML:
在templates資料夾下,建立webform.html
from flask import render_template
@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('webform.html', form=form, name=name)
在app的view函式中處理表單:
在表單被送出且所有欄位驗證函式都收到資料時回傳True。
安裝擴充套件:Flask-Bootstrap
(venv) $ pip install flask-bootstrap
Bootstrap表單模板
在建立app實例時同時初始化:
from flask_bootstrap import Bootstrap
bootstrap = Bootstrap(app)
新增一個基礎模版(base_index.html):
{% extends 'bootstrap/base.html' %}
{% block head %}
{{ super() }}
<title>{% block title %}{% endblock %} - My Application</title>
{% endblock %}
{% block content %}
<div class="container">
{% block page_content %}{% endblock %}
</div>
{% endblock %}
webform.html 繼承基礎模板,並套用wtf.html:
{% extends "base_index.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}webform{% endblock %}
{% block head %}
{{ super() }}
{% endblock %}
{% block page_content %}
<div class="page_header">
<h1>Hello,
{% if name %}
{{ name }}
{% else %}
Stranger
{% endif %}!</h1>
</div>
{{ wtf.quick_form(form) }}
{% endblock %}
# 轉址(redirect)
from flask import redirect
@app.route('/')
def index():
return redirect('http://www.example.com')
然而,當Post request一結束,表單資料即消失。
因此,需要透過session(私用的存放區)在兩次request之間"記得"它。
from flask import session, redirect, url_for
@app.route('/', methods=['GET', 'POST'])
def index():
form = NameForm()
if form.validate_on_submit():
session['name'] = form.name.data
return redirect(url_for('index'))
return render_template('webform.html', form=form, name=session.get('name'))
url_for(endpoint)
redirect(url_for('index')) 亦可寫成 redirect('/')
Request
用戶端發出request,伺服器會接收並呼叫view函式來處理。
URL map存有URL與view函式之間的對應關係。
(venv) $ python
>>> from hello import app
>>> app.url_map
from flask import flash
@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 tou have changed your name!')
session['name'] = form.name.data
return redirect(url_for('index'))
return render_template('webform.html', form=form, name=session.get('name'))
修改base_index.html基礎模板:
{% block content %}
<div class="container">
{% for message in get_flashed_messages() %}
<div class="alert alert-warning">
<button type="button" class="close" data-dismiss="alert">×</button>
{{ message }}
</div>
{% endfor %}
{% block page_content %}{% endblock %}
</div>
{% endblock %}
get_flashed_messages()
得到的訊息在下次呼叫此函數時就無法取得,故只會閃現一次。
安裝擴充套件:Flask-Moment
(venv) $ pip install flask-moment
初始化Flask-Moment
from flask_moment import Moment
moment = Moment(app)
base_index.html中,匯入Moment.js程式庫
{% block scripts %}
{{ super() }}
{{ moment.include_moment() }}
{% endblock %}
添加datetime變數
from datetime import datetime
@app.route('/')
def index():
return render_template('webform.html', current_time=datetime.utcnow())
webform.html中,用Flask-Moment來轉譯時戳
{% block content %}
<p>The local date and time is {{ moment(current_time).format('LLL') }}.</p>
<p>That was {{ moment(current_time).fromNow(refresh=True) }}</p>
{{ super() }}
{% endblock %}
base_index.html中,更改時戳轉譯的語言
{% block scripts %}
{{ super() }}
{{ moment.include_moment() }}
{{ moment.locale('es')}}
{% endblock %}
轉為西班牙文'es'