日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Flask开发系列之Web表单

發(fā)布時(shí)間:2025/3/21 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Flask开发系列之Web表单 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Flask開發(fā)系列之Web表單

?

簡(jiǎn)單示例

from flask import Flask, request, render_templateapp = Flask(__name__) @app.route('/', methods=['GET', 'POST']) def home():return render_template('home.html')@app.route('/signin', methods=['GET']) def signin_form():return render_template('form.html')@app.route('/signin', methods=['POST']) def signin():# receive the data from submitusername = request.form['username']password = request.form['password']if username == 'admin' and password == 'password':return render_template('signin-ok.html', username=username)return render_template('form.html', message='Bad username or password', username=username)if __name__ == '__main__':app.run()

?

<html> <head><title>Please Sign In</title> </head> <body>{% if message %}<p style="color:red">{{ message }}</p>{% endif %}<form action="/signin" method="post"><p>Please sign in:</p><p><input name="username" placeholder="Username" value="{{ username }}"></p><p><input name="password" placeholder="Password" type="password" value="{{ password }}"></p><p><button type="submit">Sign In</button></p></form> </body> </html> form.html <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body> <h1>hello,{{ username }}</h1> </body> </html> signin-ok

?

跨站請(qǐng)求偽造保護(hù)

默認(rèn)情況下,Flask-WTF 能保護(hù)所有表單免受跨站請(qǐng)求偽造(Cross-Site Request Forgery,
CSRF)的攻擊。惡意網(wǎng)站把請(qǐng)求發(fā)送到被攻擊者已登錄的其他網(wǎng)站時(shí)就會(huì)引發(fā) CSRF 攻擊。

?

為了實(shí)現(xiàn) CSRF 保護(hù),Flask-WTF 需要程序設(shè)置一個(gè)密鑰。Flask-WTF 使用這個(gè)密鑰生成
加密令牌,再用令牌驗(yàn)證請(qǐng)求中表單數(shù)據(jù)的真?zhèn)巍TO(shè)置密鑰的方法如示例:

app = Flask(__name__) app.config['SECRET_KEY'] = 'hard to guess string'

?

app.config 字典可用來存儲(chǔ)框架、擴(kuò)展和程序本身的配置變量。使用標(biāo)準(zhǔn)的字典句法就能 把配置值添加到 app.config 對(duì)象中。這個(gè)對(duì)象還提供了一些方法,可以從文件或環(huán)境中導(dǎo) 入配置值。 SECRET_KEY 配置變量是通用密鑰,可在 Flask 和多個(gè)第三方擴(kuò)展中使用。如其名所示,加 密的強(qiáng)度取決于變量值的機(jī)密程度。不同的程序要使用不同的密鑰,而且要保證其他人不 知道你所用的字符串。

?

表單類

使用 Flask-WTF 時(shí),每個(gè) Web 表單都由一個(gè)繼承自 Form 的類表示。這個(gè)類定義表單中的
一組字段,每個(gè)字段都用對(duì)象表示。字段對(duì)象可附屬一個(gè)或多個(gè)驗(yàn)證函數(shù)。驗(yàn)證函數(shù)用來
驗(yàn)證用戶提交的輸入值是否符合要求。

from flask_wtf import FlaskForm from wtforms import StringField, SubmitField, PasswordField,TextAreaField,HiddenFieldfrom wtforms.validators import DataRequired, Length, Email class NameForm(FlaskForm):title = StringField('Title', validators=[DataRequired()])category = StringField('Category')content = TextAreaField('Content')post_id = HiddenField('post_id')submit = SubmitField('submit')

StringField 構(gòu)造函數(shù)中的可選參數(shù) validators 指定一個(gè)由驗(yàn)證函數(shù)組成的列表,在接受
用戶提交的數(shù)據(jù)之前驗(yàn)證數(shù)據(jù)。驗(yàn)證函數(shù) Required() 確保提交的字段不為空。

WTForms支持的HTML標(biāo)準(zhǔn)字段

字段類型 說 明 StringField 文本字段 TextAreaField 多行文本字段 PasswordField 密碼文本字段 HiddenField 隱藏文本字段 DateField 文本字段,值為 datetime.date 格式 DateTimeField 文本字段,值為 datetime.datetime 格式 IntegerField 文本字段,值為整數(shù) DecimalField 文本字段,值為 decimal.Decimal FloatField 文本字段,值為浮點(diǎn)數(shù) BooleanField 復(fù)選框,值為 True 和 False RadioField 一組單選框 SelectField 下拉列表 SelectMultipleField 下拉列表,可選擇多個(gè)值 FileField 文件上傳字段 SubmitField 表單提交按鈕 FormField 把表單作為字段嵌入另一個(gè)表單 FieldList 一組指定類型的字段

WTForms驗(yàn)證函數(shù)

驗(yàn)證函數(shù)   說 明 Email     驗(yàn)證電子郵件地址 EqualTo    比較兩個(gè)字段的值;常用于要求輸入兩次密碼進(jìn)行確認(rèn)的情況 IPAddress 驗(yàn)證 IPv4 網(wǎng)絡(luò)地址 Length 驗(yàn)證輸入字符串的長(zhǎng)度 NumberRange 驗(yàn)證輸入的值在數(shù)字范圍內(nèi) Optional 無輸入值時(shí)跳過其他驗(yàn)證函數(shù) Required 確保字段中有數(shù)據(jù) Regexp 使用正則表達(dá)式驗(yàn)證輸入值 URL 驗(yàn)證 URL AnyOf 確保輸入值在可選值列表中 NoneOf 確保輸入值不在可選值列表中

?

?

表單渲染

兩種方式:

  • flask-bootstrap渲染
  • 一般渲染(常用)

flask-bootstrap渲染

flask-boostrap是bootstrap的flask擴(kuò)張,它可以提供wtf.html文件中的form_field函數(shù)來進(jìn)行渲染:

{% import "bootstrap/wtf.html" as wtf %} <form class="form" method="POST">{{ form.hidden_tag() }}{{ wtf.form_field(form.title) }}{{ wtf.form_field(form.content) }}...{{ wtf.form_field(form.submit) }} </form>

注意,如果有多個(gè)隱藏字段,可以使用form.hidden_tag()渲染所以隱藏字段。
另外Flask-WTF支持跨站請(qǐng)求偽造保護(hù),表單類創(chuàng)建時(shí)會(huì)自動(dòng)創(chuàng)建一個(gè)CSRF字段,你需要在表單里渲染這個(gè)字段:{{ form.csrf_token }}。
還有一種快速渲染方式:

{% import "bootstrap/wtf.html" as wtf %} {{ wtf.quick_form(form) }}

?

一般渲染(常用)

直接在對(duì)應(yīng)的html模版中引入字段:

{% extends "base.html" %} {% block title %}Flask{% endblock %} {% block body %} <form class="form" method="POST">{{ form.hidden_tag() }}{{ form.title.label }}{{ form.title() }}{{ form.content.label }}{{ form.content() }}{{ form.submit() }} </form> {% endblock %} <html> <head>{% block head %}<title>{% block title %}{% endblock %} - My Application</title>{% endblock %} </head> <body>{% block body %}{% endblock %} </body> </html> base.html

另外還可以在字段中加入有些屬性,比如要加入class:

form.title(class_="form-control")

轉(zhuǎn)化為html的效果:

<input type="text" name="title" value="title" class="form-control" id="title" />

上面的渲染如果有很多字段的話,一個(gè)個(gè)寫出來會(huì)覺得很繁瑣,在實(shí)際開發(fā)中,可以創(chuàng)建一個(gè)_form.html文件來處理。
_form.html:

{% macro render(form) -%}{% for field in form %}{% if field.type in ['CSRFTokenField', 'HiddenField'] %}<!--CSR和隱藏字段-->{{ field() }}{% elif field.type == "BooleanField" %}<!--Boolean類型字段--><div class="checkbox"><label>{{ field() }} {{ field.label }}</label></div>{% elif field.type == "RadioField" %}<!--Radio類型字段-->{{ field.label }}{% for subfield in field %}<div class="radio"><label>{{ subfield }} {{ subfield.label }}</label></div>{% endfor %}{% else %}<div class="clearfix {% if field.errors %}has-error{% endif %} form-group"><!--剩下的一般類型字段-->{{ field.label }}{% if field.type == "TextAreaField" %}{{ field(class_="form-control", rows=10) }}{% else %}{{ field(class_="form-control") }}{% endif %}{% if field.errors or field.help_text %}<span class="help-block">{% if field.errors %}{{ field.errors|join(' ') }}{% else %}{{ field.help_text }}{% endif %}</span>{% endif %}</div>{% endif %} {% endfor %}{% endmacro %}

接著在對(duì)應(yīng)的html模版中進(jìn)行引用 :

{% import "_form.html" as forms %}<!--引入_form--><form method="POST" action="">{{ forms.render(form) }}<!--使用_form對(duì)form來進(jìn)行渲染-->

?

?一個(gè)簡(jiǎn)單的例子

from flask import Flask,render_template from flask_wtf import FlaskForm from wtforms import StringField, SubmitField from flask_bootstrap import Bootstrap from wtforms.validators import Requiredapp = Flask(__name__) app.config["SECRET_KEY"] = "12345678" bootstrap = Bootstrap(app)class NameForm(FlaskForm):name = StringField('What is your name?', validators=[Required()])submit = SubmitField('Submit')@app.route('/', methods=['GET', 'POST']) def index():name = None#實(shí)例化表單類form = NameForm()# 如果提交的數(shù)據(jù)驗(yàn)證通過,則返回Trueif form.validate_on_submit():name = form.name.dataform.name.data = ''return render_template('index.html', form=form, name=name)if __name__ == '__main__':app.run(debug=True)# Flask提供的render_template函數(shù)把Jinja2模板引擎集成到了程序中。# render_template函數(shù)的第一個(gè)參數(shù)是模板的文件名。# 隨后的參數(shù)都是鍵值對(duì),表示模板中變量對(duì)應(yīng)的真實(shí)值。

?

{% extends "base.html" %} {% import "bootstrap/wtf.html" as wtf %} {% block title %}Flasky{% endblock %} {% block page_content %} <div class="page-header"> <h1>Hello, {% if name %}{{ name }}{% else %}Stranger{% endif %}!</h1> </div> {{ wtf.quick_form(form) }} {% endblock %} index.html {% extends "bootstrap/base.html" %} {% block title %}Flasky{% endblock %} {% block navbar %} <div class="navbar navbar-inverse" role="navigation"><div class="container"><div class="navbar-header"><button type="button" class="navbar-toggle"data-toggle="collapse" data-target=".navbar-collapse"><span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a class="navbar-brand" href="/">Flasky</a></div><div class="navbar-collapse collapse"><ul class="nav navbar-nav"><li><a href="/">Home</a></li></ul></div></div> </div> {% endblock %} {% block content %} <div class="container">{% block page_content %}{% endblock %} </div> {% endblock %} base.html

?

?

重定向和用戶會(huì)話

from flask import Flask, render_template, session, redirect, url_for @app.route('/', methods=['GET', 'POST']) def index():form = NameForm()if form.validate_on_submit():session['name'] = form.name.datareturn redirect(url_for('index'))return render_template('index.html', form=form, name=session.get('name')) 前面到的代碼存在一個(gè)可用性問題。用戶輸入名字后提交表單,然后點(diǎn)擊瀏覽器的刷 新按鈕,會(huì)看到一個(gè)莫名其妙的警告,要求在再次提交表單之前進(jìn)行確認(rèn)。之所以出現(xiàn)這 種情況,是因?yàn)樗⑿马?yè)面時(shí)瀏覽器會(huì)重新發(fā)送之前已經(jīng)發(fā)送過的最后一個(gè)請(qǐng)求。如果這個(gè) 請(qǐng)求是一個(gè)包含表單數(shù)據(jù)的 POST 請(qǐng)求,刷新頁(yè)面后會(huì)再次提交表單。大多數(shù)情況下,這并 不是理想的處理方式。 很多用戶都不理解瀏覽器發(fā)出的這個(gè)警告。基于這個(gè)原因,最好別讓 Web 程序把 POST 請(qǐng) 求作為瀏覽器發(fā)送的最后一個(gè)請(qǐng)求。 這種需求的實(shí)現(xiàn)方式是,使用重定向作為 POST 請(qǐng)求的響應(yīng),而不是使用常規(guī)響應(yīng)。重定 向是一種特殊的響應(yīng),響應(yīng)內(nèi)容是 URL,而不是包含 HTML 代碼的字符串。瀏覽器收到 這種響應(yīng)時(shí),會(huì)向重定向的 URL 發(fā)起 GET 請(qǐng)求,顯示頁(yè)面的內(nèi)容。這個(gè)頁(yè)面的加載可能 要多花幾微秒,因?yàn)橐劝训诙€(gè)請(qǐng)求發(fā)給服務(wù)器。除此之外,用戶不會(huì)察覺到有什么不 同。現(xiàn)在,最后一個(gè)請(qǐng)求是 GET 請(qǐng)求,所以刷新命令能像預(yù)期的那樣正常使用了。這個(gè)技 巧稱為 Post/ 重定向 /Get 模式。 但這種方法會(huì)帶來另一個(gè)問題。程序處理 POST 請(qǐng)求時(shí),使用 form.name.data 獲取用戶輸 入的名字,可是一旦這個(gè)請(qǐng)求結(jié)束,數(shù)據(jù)也就丟失了。因?yàn)檫@個(gè) POST 請(qǐng)求使用重定向處 理,所以程序需要保存輸入的名字,這樣重定向后的請(qǐng)求才能獲得并使用這個(gè)名字,從而構(gòu)建真正的響應(yīng)。 程序可以把數(shù)據(jù)存儲(chǔ)在用戶會(huì)話中,在請(qǐng)求之間“記住”數(shù)據(jù)。用戶會(huì)話是一種私有存 儲(chǔ),存在于每個(gè)連接到服務(wù)器的客戶端中。用戶會(huì)話,它是請(qǐng)求上下文中的變量,名為 session ,像標(biāo)準(zhǔn)的 Python 字典一樣操作。 注意:默認(rèn)情況下,用戶會(huì)話保存在客戶端 cookie 中,使用設(shè)置的 SECRET_KEY 進(jìn) 行加密簽名。如果篡改了 cookie 中的內(nèi)容,簽名就會(huì)失效,會(huì)話也會(huì)隨之 失效。

代碼分析

局部變量 name 被用于存儲(chǔ)用戶在表單中輸入的名字。這個(gè)變量現(xiàn) 在保存在用戶會(huì)話中,即 session['name'] ,所以在兩次請(qǐng)求之間也能記住輸入的值。 現(xiàn)在,包含合法表單數(shù)據(jù)的請(qǐng)求最后會(huì)調(diào)用 redirect() 函數(shù)。 redirect() 是個(gè)輔助函數(shù), 用來生成 HTTP 重定向響應(yīng)。 redirect() 函數(shù)的參數(shù)是重定向的 URL,這里使用的重定向 URL 是程序的根地址,因此重定向響應(yīng)本可以寫得更簡(jiǎn)單一些,寫成 redirect('/') ,但 卻會(huì)使用 Flask 提供的 URL 生成函數(shù) url_for() 。推薦使用 url_for() 生成 URL,因?yàn)檫@ 個(gè)函數(shù)使用 URL 映射生成 URL,從而保證 URL 和定義的路由兼容,而且修改路由名字后 依然可用。 url_for() 函數(shù)的第一個(gè)且唯一必須指定的參數(shù)是端點(diǎn)名,即路由的內(nèi)部名字。默認(rèn)情 況下,路由的端點(diǎn)是相應(yīng)視圖函數(shù)的名字。在這個(gè)示例中,處理根地址的視圖函數(shù)是 index() ,因此傳給 url_for() 函數(shù)的名字是 index 。 最后一處改動(dòng)位于 render_function() 函數(shù)中,使用 session.get('name') 直接從會(huì)話中讀 取 name 參數(shù)的值。和普通的字典一樣,這里使用 get() 獲取字典中鍵對(duì)應(yīng)的值以避免未找 到鍵的異常情況,因?yàn)閷?duì)于不存在的鍵, get() 會(huì)返回默認(rèn)值 None 。

?



參考鏈接:
1.https://greyli.com/flask-form-create-and-render/
2.WTForms官方文檔
3.http://flask.pocoo.org/docs/1.0/patterns/wtforms/
4.https://stackoverflow.com/questions/20905188/flask-wtforms-validation-always-false 5.《FlaskWeb開發(fā):基于python的Web應(yīng)用開發(fā)實(shí)戰(zhàn)

?

轉(zhuǎn)載于:https://www.cnblogs.com/-wenli/p/11042961.html

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的Flask开发系列之Web表单的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。