FlaskForm,是Flask框架中的一個表單處理擴展,它可以幫我們更方便地管理表單,實現表單驗證、提交等功能,減輕了我們的工作壓力。本文從多個方面對FlaskForm做詳細的闡述,以便讀者更好地理解與使用它。
一、FlaskForm二級聯動
在我們的Web應用中,常常需要進行二級聯動功能的實現,比如省、市、區的地址選擇,或者是商品類型、子類的選擇等等。使用FlaskForm可以很方便地實現這樣的功能。
首先我們需要定義表單類,下面是一個例子:
from wtforms import SelectField, Form, validators
choices_a = [("", "請選擇..."), ("1", "選項1"), ("2", "選項2"), ("3", "選項3"), ("4", "選項4")]
choices_b = [("", "請選擇..."), ("a", "選項A"), ("b", "選項B"), ("c", "選項C"), ("d", "選項D")]
class TestForm(Form):
select_a = SelectField("級別1", choices=choices_a, validators=[validators.DataRequired()])
select_b = SelectField("級別2", choices=choices_b, validators=[validators.DataRequired()])
接下來,我們需要在視圖函數中使用這個表單類。在GET請求中,我們需要傳遞一個空的表單實例到前端,讓用戶進行選擇;在POST請求中,我們需要對用戶選擇的數據進行處理並返回結果。
from flask import render_template, request
@app.route("/double_select", methods=["GET", "POST"])
def double_select():
form = TestForm(request.form)
if request.method == "POST" and form.validate():
select_a = form.select_a.data
select_b = form.select_b.data
# 處理選項數據...
return "success"
return render_template("double_select.html", form=form)
在前端模板中,我們需要利用FlaskForm提供的表單插件來渲染二級聯動的功能。下面是一個例子:
<form method="post" action="">
{{ form.select_a.label }} {{ form.select_a }}
{{ form.select_b.label }} {{ form.select_b }}
<input type="submit" value="提交">
</form>
{{ form.hidden_tag() }}
...
<script>
$(function() {
$("#select_a").on("change", function() {
$.get("/get_select_b", {"select_a": $(this).val()}, function(data) {
var optionsHtml = "";
$.each(data, function(key, value) {
optionsHtml += "<option value='" + key + "'>" + value + "</option>";
});
$("#select_b").html(optionsHtml);
}, "json");
});
});
</script>
在這個例子中,我們使用了flask_wtf插件來渲染表單,使用了jQuery庫來實現異步加載子類選項數據的功能。
二、FlaskForm CSRF
在我們的Web應用中,跨站請求偽造(CSRF)是一種常見的安全漏洞,攻擊者可以通過構造惡意請求來實現用戶信息、資金等的竊取或者篡改。使用FlaskForm提供的CSRF保護可以很好地防禦這種安全漏洞。
在Flask中,我們可以通過在FlaskForm實例中設置SECRET_KEY來啟用CSRF保護。下面是一個例子:
from flask_wtf.csrf import CSRFProtect
app = Flask(__name__)
app.config["SECRET_KEY"] = "your-secret-key"
csrf = CSRFProtect(app)
這裡我們設置了一個隨機的SECRET_KEY,用來加密和驗證TOKEN,保證應用的安全性。然後我們使用CSRFProtect包裝我們的Flask應用來啟用CSRF保護。
啟用CSRF保護後,我們需要在前端模板中使用FlaskForm提供的表單插件來渲染form標籤,其中包含了_csrf_token的隱藏字段。下面是一個例子:
<form method="post" action="">
{{ form.username.label }} {{ form.username }}
{{ form.password.label }} {{ form.password }}
<input type="submit" value="提交">
</form>
{{ form.hidden_tag() }}
當我們在POST請求中提交表單數據時,FlaskForm會自動從表單數據中獲取_csrf_token字段,並且與其中包含的加密簽名進行比較驗證,如果驗證失敗則拋出異常。
三、FlaskForm聯合查詢
在我們的Web應用中,常常需要實現複雜的聯合查詢功能,比如商品名稱、類型、價格的多條件組合查詢等等。使用FlaskForm可以很方便地實現這樣的功能。
FlaskForm提供了各種表單字段類型來方便我們實現多條件查詢,比如StringField、SelectField、DateField等。下面是一個例子:
from flask_wtf import FlaskForm
from wtforms import StringField, SelectField, DateField
from wtforms.validators import DataRequired
class QueryForm(FlaskForm):
name = StringField("名稱")
category = SelectField("分類", choices=[("all", "全部"), ("1", "分類1"), ("2", "分類2")])
price_min = StringField("最小价格")
price_max = StringField("最大價格")
create_time = DateField("創建日期", format="%Y-%m-%d")
update_time = DateField("更新日期", format="%Y-%m-%d")
在視圖函數中,我們使用這個表單類來接收並且處理用戶提交的查詢條件。下面是一個例子:
@app.route("/query", methods=["GET", "POST"])
def query():
form = QueryForm(request.form)
if request.method == "POST" and form.validate():
name = form.name.data.strip() or None
category = form.category.data
if category == "all":
category = None
try:
price_min = float(form.price_min.data.strip())
except:
price_min = None
try:
price_max = float(form.price_max.data.strip())
except:
price_max = None
create_time = form.create_time.data or None
update_time = form.update_time.data or None
# 處理查詢條件...
return "success"
return render_template("query.html", form=form)
在前端模板中,我們可以使用FlaskForm提供的表單插件來渲染表單。下面是一個例子:
<form method="post" action="">
{{ form.name.label }} {{ form.name }}
{{ form.category.label }} {{ form.category }}
{{ form.price_min.label }} {{ form.price_min }}
{{ form.price_max.label }} {{ form.price_max }}
{{ form.create_time.label }} {{ form.create_time }}
{{ form.update_time.label }} {{ form.update_time }}
<input type="submit" value="查詢">
</form>
{{ form.hidden_tag() }}
四、FlaskForm CSRF取消
在某些情況下,我們可能需要在特定表單中取消FlaskForm的CSRF保護,比如在我們需要讓用戶在不登錄的情況下進行某些操作的時候。FlaskForm提供了一個@csrf_exempt裝飾器來完成這個功能。
在視圖函數中,我們只需要在函數上方加上@csrf_exempt裝飾器即可取消FlaskForm的CSRF保護。下面是一個例子:
from flask_wtf.csrf import csrf_exempt
@app.route("/some_action", methods=["POST"])
@csrf_exempt
def some_action():
# 處理不需要CSRF保護的操作...
return "success"
五、FlaskForm Python三級聯動
除了常見的二級聯動,有些特定的業務場景可能需要實現三級或者更多級聯動的功能。FlaskForm同樣可以很方便地實現這些功能。
在實現三級聯動的時候,我們需要使用三個FlaskForm實例來分別表示三個下拉框。下面是一個例子:
from wtforms import Form, SelectField
class SelectAForm(Form):
select_a = SelectField("級別1")
class SelectBForm(Form):
select_b = SelectField("級別2")
class SelectCForm(Form):
select_c = SelectField("級別3")
然後我們需要在視圖函數中使用這三個表單來實現三級聯動。在GET請求中,我們需要傳遞一族空表單到前端;在POST請求中,我們需要處理用戶的選擇,並且動態返回下一級的選項。下面是一個例子:
@app.route('/three_levels')
def three_levels():
select_a_form = SelectAForm()
select_b_form = SelectBForm()
select_c_form = SelectCForm()
return render_template("three_levels.html", select_a_form=select_a_form, select_b_form=select_b_form, select_c_form=select_c_form)
@app.route("/get_b")
def get_b():
select_b_form = SelectBForm()
id = request.args.get("id", 0, type=int)
if id == 1:
select_b_form.select_b.choices = [("", "選擇..."), (1, "選項1"), (2, "選項2"), (3, "選項3")]
elif id == 2:
select_b_form.select_b.choices = [("", "選擇..."), (4, "選項4"), (5, "選項5"), (6, "選項6")]
elif id == 3:
select_b_form.select_b.choices = [("", "選擇..."), (7, "選項7"), (8, "選項8"), (9, "選項9")]
return jsonify(select_b_form.select_b.choices)
@app.route("/get_c")
def get_c():
select_c_form = SelectCForm()
id = request.args.get("id", 0, type=int)
if id == 1:
select_c_form.select_c.choices = [("", "選擇..."), (1, "選項1"), (2, "選項2"), (3, "選項3")]
elif id == 2:
select_c_form.select_c.choices = [("", "選擇..."), (4, "選項4"), (5, "選項5"), (6, "選項6")]
elif id == 3:
select_c_form.select_c.choices = [("", "選擇..."), (7, "選項7"), (8, "選項8"), (9, "選項9")]
return jsonify(select_c_form.select_c.choices)
在前端模板中,我們需要利用FlaskForm提供的表單插件來渲染三個下拉框。其中第一級會觸發AJAX請求,返回第二級的選項;第二級會觸發AJAX請求,返回第三級的選項。下面是一個例子:
<form>
{{ select_a_form.select_a.label }} {{ select_a_form.select_a }}
{{ select_b_form.select_b.label }} {{ select_b_form.select_b }}
{{ select_c_form.select_c.label }} {{ select_c_form.select_c }}
</form><script>
$(function() {
$("#select_a").on("change", function() {
var id = $(this).val();
if (id) {
$.get("/get_b", {"id": id}, function(data) {
var optionsHtml = "<option value=''>-</option>";
$.each(data, function(key, value) {
optionsHtml += "<option value='" + key + "'>" + value + "</option>";
});
$("#select_b").html(optionsHtml).change();
}, "json");
} else {
$("#select_b").html("<option value=''>-</option>");
$("#select_c").html("<option value=''>-</option>");
}
});
原創文章,作者:ZQSQ,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/138098.html
微信掃一掃
支付寶掃一掃