摘要:你打了個(gè)響指然后開始致力于你想寫的棒極了的網(wǎng)絡(luò)應(yīng)用程序你寫完一些頁面最后你需要著手處理令人討厭的任務(wù)處理和驗(yàn)證表單輸入進(jìn)入開始但是為什么我需要另一個(gè)框架呢好吧一些網(wǎng)絡(luò)應(yīng)用程序框架采用數(shù)據(jù)庫模型和表單處理相結(jié)合的方法同時(shí)這對很基本的創(chuàng)建更新視
你打了個(gè)響指, 然后開始致力于你想寫的棒極了的 Python 網(wǎng)絡(luò)應(yīng)用程序. 你寫完一些頁面, 最后你需要著手處理令人討厭的任務(wù):處理和驗(yàn)證表單輸入. 進(jìn)入(開始)WTForms.
但是, 為什么我需要另一個(gè)框架呢?好吧, 一些網(wǎng)絡(luò)應(yīng)用程序框架采用數(shù)據(jù)庫模型和表單處理相結(jié)合的方法. 同時(shí)這對很基本的創(chuàng)建/更新視圖函數(shù)是很方便的, 可能性是不是每個(gè)你需要的表單都能直接映射到一個(gè)數(shù)據(jù)庫模型. 也許你已經(jīng)使用通用的表單處理框架, 只是你想要定制這些表單域的 HTML 代碼生成, 并且定義屬于你的驗(yàn)證器.
使用 WTForms, 你能生成屬于你的表單域的 HTML 代碼, 此外我們允許你在模板中定制它. 這允許你維持獨(dú)立的代碼和展現(xiàn), 并把這些凌亂的參數(shù)保留在 Python 代碼之外. 因?yàn)槲覀儬幦∷神詈? 同樣的, 你應(yīng)該可以在你喜歡的任意的模板引擎中這么做.
下載和安裝備注: 本人未過四級, 翻譯水平有限, 歡迎指正.
安裝 WTForms 最簡單的方式是使用 easy_install 和 pip:
basheasy_install WTForms # or pip install WTForms
你可以從 PyPI 手動(dòng) 下載 WTForms 然后運(yùn)行 python setup.py install .
如果你是那種喜歡這一切風(fēng)險(xiǎn)的人, 就運(yùn)行來自 Git 的最新版本, 你能夠獲取最新變更集的 打包版本, 或者前往 項(xiàng)目主頁 克隆代碼倉庫.
主要概念Forms 類是 WTForms 的核心容器. 表單(Forms)表示域(Fields)的集合, 域能通過表單的字典形式或者屬性形式訪問.
Fields(域)做最繁重的工作. 每個(gè)域(field)代表一個(gè)數(shù)據(jù)類型, 并且域操作強(qiáng)制表單輸入為那個(gè)數(shù)據(jù)類型. 例如, InputRequired 和 StringField 表示兩種不同的數(shù)據(jù)類型. 域除了包含的數(shù)據(jù)(data)之外, 還包含大量有用的屬性, 例如標(biāo)簽、描述、驗(yàn)證錯(cuò)誤的列表.
每個(gè)域(field)擁有一個(gè)Widget(部件)實(shí)例. Widget 的工作是渲染域(field)的HTML表示. 每個(gè)域可以指定Widget實(shí)例, 但每個(gè)域默認(rèn)擁有一個(gè)合理的widget. 有些域是簡單方便的, 比如 TextAreaField 就僅僅是默認(rèn)部件(widget) 為 TextArea 的
StringField.
為了指定驗(yàn)證規(guī)則, 域包含驗(yàn)證器(Validators)列表.
開始讓我們直接進(jìn)入正題并定義我們的第一個(gè)表單::
pythonfrom wtforms import Form, BooleanField, StringField, validators class RegistrationForm(Form): username = StringField("Username", [validators.Length(min=4, max=25)]) email = StringField("Email Address", [validators.Length(min=6, max=35)]) accept_rules = BooleanField("I accept the site rules", [validators.InputRequired()])
當(dāng)你創(chuàng)建一個(gè)表單(form), 你定義域(field)的方法類似于很多ORM定義它們的列(columns):通過定義類變量, 即域的實(shí)例.
因?yàn)楸韱问浅R?guī)的 Python 類, 你可以很容易地把它們擴(kuò)展成為你期望的::
pythonclass ProfileForm(Form): birthday = DateTimeField("Your Birthday", format="%m/%d/%y") signature = TextAreaField("Forum Signature") class AdminProfileForm(ProfileForm): username = StringField("Username", [validators.Length(max=40)]) level = IntegerField("User Level", [validators.NumberRange(min=0, max=10)])
通過子類, AdminProfileForm 類獲得了已經(jīng)定義的 ProfileForm 類的所有域. 這允許你輕易地在不同表單之間共享域的共同子集, 例如上面的例子, 我們增加 admin-only 的域到 ProfileForm.
使用表單使用表單和實(shí)例化它一樣簡單. 想想下面這個(gè)django風(fēng)格的視圖函數(shù), 它使用之前定義的 RegistrationForm 類::
pythondef register(request): form = RegistrationForm(request.POST) if request.method == "POST" and form.validate(): user = User() user.username = form.username.data user.email = form.email.data user.save() redirect("register") return render_response("register.html", form=form)
首先, 我們實(shí)例化表單, 給它提供一些 request.POST 中可用的數(shù)據(jù). 然后我們檢查請求(request)是不是使用 POST 方式, 如果它是, 我們就驗(yàn)證表單, 并檢查用戶遵守這些規(guī)則. 如果成功了, 我們創(chuàng)建新的 User 模型, 并從已驗(yàn)證的表單分派數(shù)據(jù)給它, 最后保存它.
編輯現(xiàn)存對象我們之前的注冊例子展示了如何為新條目接收輸入并驗(yàn)證, 只是如果我們想要編輯現(xiàn)有對象怎么辦?很簡單::
pythondef edit_profile(request): user = request.current_user form = ProfileForm(request.POST, user) if request.method == "POST" and form.validate(): form.populate_obj(user) user.save() redirect("edit_profile") return render_response("edit_profile.html", form=form)
這里, 我們通過給表單同時(shí)提供 request.POST 和用戶(user)對象來實(shí)例化表單. 通過這樣做, 表單會(huì)從 user 對象得到在未在提交數(shù)據(jù)中出現(xiàn)的任何數(shù)據(jù).
我們也使用表單的populate_obj方法來重新填充用戶對象, 用已驗(yàn)證表單的內(nèi)容. 這個(gè)方法提供便利, 用于當(dāng)域(field)名稱和你提供數(shù)據(jù)的對象的名稱匹配時(shí). 通常的, 你會(huì)想要手動(dòng)分配值, 但對于這個(gè)簡單例子, 它是最好的. 它也可以用于CURD和管理(admin)表單.
在控制臺(tái)中探索WTForms 表單是非常簡單的容器對象, 也許找出表單中什么對你有用的最簡單的方法就是在控制臺(tái)中玩弄表單:
python>>> from wtforms import Form, StringField, validators >>> class UsernameForm(Form): ... username = StringField("Username", [validators.Length(min=5)], default=u"test") ... >>> form = UsernameForm() >>> form["username"]>>> form.username.data u"test" >>> form.validate() False >>> form.errors {"username": [u"Field must be at least 5 characters long."]}
我們看到的是當(dāng)你實(shí)例化一個(gè)表單的時(shí)候, 表單包含所有域的實(shí)例, 訪問域可以通過字典形式或者屬性形式. 這些域擁有它們自己的屬性, 就和封閉的表單一樣.
當(dāng)我們驗(yàn)證表單, 它返回邏輯假, 意味著至少一個(gè)驗(yàn)證規(guī)則不滿足. form.errors 會(huì)給你一個(gè)所有錯(cuò)誤的概要.
python>>> form2 = UsernameForm(username=u"Robert") >>> form2.data {"username": u"Robert"} >>> form2.validate() True
這次, 我們實(shí)例化 UserForm 時(shí)給 username 傳送一個(gè)新值, 驗(yàn)證表單是足夠了.
表單如何獲取數(shù)據(jù)除了使用前兩個(gè)參數(shù)(formdata和obj)提供數(shù)據(jù)之外, 你可以傳送關(guān)鍵詞參數(shù)來填充表單. 請注意一些參數(shù)名是被保留的: formdata, obj, prefix.
formdata比obj優(yōu)先級高, obj比關(guān)鍵詞參數(shù)優(yōu)先級高. 例如:
pythondef change_username(request): user = request.current_user form = ChangeUsernameForm(request.POST, user, username="silly") if request.method == "POST" and form.validate(): user.username = form.username.data user.save() return redirect("change_username") return render_response("change_username.html", form=form)
雖然你在實(shí)踐中幾乎從未一起使用所有3種方式, 舉例說明WTForms是如何查找 username 域:
如果表單被提交(request.POST非空), 則處理表單輸入. 實(shí)踐中, 即使這個(gè)域沒有 表單輸入, 而如果存在任何種類的表單輸入, 那么我們會(huì)處理表單輸入.
如果沒有表單輸入, 則按下面的順序嘗試:
檢查 user 是否有一個(gè)名為 username 的屬性.
檢查是否提供一個(gè)名為 username 的關(guān)鍵詞參數(shù).
最后, 如果都失敗了, 使用域的默認(rèn)值, 如果有的話.
驗(yàn)證器WTForms中的驗(yàn)證器(Validators)為域(field)提供一套驗(yàn)證器, 當(dāng)包含域的表單進(jìn)行驗(yàn)證時(shí)運(yùn)行. 你提供驗(yàn)證器可通過域構(gòu)造函數(shù)的第二個(gè)參數(shù)validators:
pythonclass ChangeEmailForm(Form): email = StringField("Email", [validators.Length(min=6, max=120), validators.Email()])
你可以為一個(gè)域提供任意數(shù)量的驗(yàn)證器. 通常, 你會(huì)想要提供一個(gè)定制的錯(cuò)誤消息:
pythonclass ChangeEmailForm(Form): email = StringField("Email", [ validators.Length(min=6, message=_(u"Little short for an email address?")), validators.Email(message=_(u"That"s not a valid email address.")) ])
這通常更好地提供你自己的消息, 作為必要的默認(rèn)消息是通用的. 這也是提供本地化錯(cuò)誤消息的方法.
對于內(nèi)置的驗(yàn)證器的列表, 查閱 Validators.
渲染域渲染域和強(qiáng)制它為字符串一樣簡單:
python>>> from wtforms import Form, StringField >>> class SimpleForm(Form): ... content = StringField("content") ... >>> form = SimpleForm(content="foobar") >>> str(form.content) "" >>> unicode(form.content) u""
然而, 渲染域的真正力量來自于它的 __call__() 方法. 調(diào)用(calling)域, 你可以提供關(guān)鍵詞參數(shù), 它們會(huì)在輸出中作為HTML屬性注入.
python>>> form.content(style="width: 200px;", class_="bar") u""
現(xiàn)在, 讓我們應(yīng)用這個(gè)力量在 Jinja 模板中渲染表單. 首先, 我們的表單:
pythonclass LoginForm(Form): username = StringField("Username") password = PasswordField("Password") form = LoginForm()
然后是模板文件:
jinja {{ form.username.label }}: {{ form.username(class="css_class") }}{{ form.password.label }}: {{ form.password() }}
相同的, 如果你使用 Django 模板, 當(dāng)你想要傳送關(guān)鍵詞參數(shù)時(shí), 你可以使用我們在Django擴(kuò)展中提供的模板標(biāo)簽form_field:
django{% load wtforms %} {{ form.username.label }}: {% form_field form.username class="css_class" %}{{ form.password.label }}: {{ form.password }}
這兩個(gè)將會(huì)輸出:
html ::
WTForms是模板引擎不可知的, 同時(shí)會(huì)和任何允許屬性存取、字符串強(qiáng)制(string coercion)、函數(shù)調(diào)用的引擎共事. 在 Django 模板中, 當(dāng)你不能傳送參數(shù)時(shí), 模板標(biāo)簽 form_field 提供便利.
顯示錯(cuò)誤消息現(xiàn)在我們的表單擁有一個(gè)模板, 讓我們增加錯(cuò)誤消息::
jinja {{ form.username.label }}: {{ form.username(class="css_class") }}{% if form.username.errors %}{% for error in form.username.errors %}
{% endif %}- {{ error }}
{% endfor %}{{ form.password.label }}: {{ form.password() }}{% if form.password.errors %}{% for error in form.password.errors %}
{% endif %}- {{ error }}
{% endfor %}
如果你喜歡在頂部顯示大串的錯(cuò)誤消息, 也很簡單:
jinja{% if form.errors %}{% for field_name, field_errors in form.errors|dictsort if field_errors %} {% for error in field_errors %}
{% endif %}- {{ form[field_name].label }}: {{ error }}
{% endfor %} {% endfor %}
由于錯(cuò)誤處理會(huì)變成相當(dāng)冗長的事情, 在你的模板中使用 Jinja 宏(macros, 或者相同意義的) 來減少引用是更好的. (例子)
定制驗(yàn)證器這有兩種方式定制的驗(yàn)證器. 通過定義一個(gè)定制的驗(yàn)證器并在域中使用它:
pythonfrom wtforms.validators import ValidationError def is_42(form, field): if field.data != 42: raise ValidationError("Must be 42") class FourtyTwoForm(Form): num = IntegerField("Number", [is_42])
或者通過提供一個(gè)在表單內(nèi)的特定域(in-form field-specific)的驗(yàn)證器:
pythonclass FourtyTwoForm(Form): num = IntegerField("Number") def validate_num(form, field): if field.data != 42: raise ValidationError(u"Must be 42")
對于更多帶參數(shù)的復(fù)雜驗(yàn)證器, 查閱 Custom validators部分.
下一步速成課程只是粗略地講述如何在你的應(yīng)用程序中開始使用WTForms處理表單輸入和驗(yàn)證. 對于更多的信息, 你要查閱下面的:
WTForms 文檔 擁有整個(gè)庫的API文檔.
解決特定問題 能幫助你處理WTForms和其它框架的特定的整合問題.
郵件列表是你獲得幫助, 討論WTForms bugs, 建議新特性的地方.
英文原文:http://pythonhosted.org//WTForms/crash_course.html
譯文原文:http://flask123.sinaapp.com/article/60/
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/45356.html
摘要:語言行為及特征狀態(tài)看不懂任何英語技術(shù),英語文檔,凡事沒有培訓(xùn)部在搞的,只有英文文檔的東西國內(nèi)一律沒大公司在用,都非主流,排斥英文文檔和新技術(shù),以及各種超出他學(xué)習(xí)能力范圍的技術(shù)。 在撰寫此文前首先必須申明的是本人不鄙視任何一種框架,也無意于挑起PHP框架間的戰(zhàn)爭,更沒有貶低某個(gè)框架使用者的用意,本文純粹個(gè)人的看法。你可以認(rèn)為我無知也好,或者裝逼也好,請不要試著在任何情況下,隨便發(fā)起言語的...
摘要:做一個(gè)搬運(yùn)工,希望自己能努力學(xué)習(xí),也希望大神們的東西能讓更多的人看到不斷更新更新日志新增了網(wǎng)絡(luò)安全分類,整理了排版布局新增了的鏈接,將一些雜七雜八的東西弄到了一篇新文章上了,叫做積累與雜貨鋪一以及相關(guān)教程的規(guī)范與相關(guān)中文學(xué)習(xí)大本營中文文檔簡 做一個(gè)搬運(yùn)工,希望自己能努力學(xué)習(xí),也希望大神們的東西能讓更多的人看到 不斷更新 更新日志:2017.10.13 新增了網(wǎng)絡(luò)安全分類,整理了排版布局...
摘要:做一個(gè)搬運(yùn)工,希望自己能努力學(xué)習(xí),也希望大神們的東西能讓更多的人看到不斷更新更新日志新增了網(wǎng)絡(luò)安全分類,整理了排版布局新增了的鏈接,將一些雜七雜八的東西弄到了一篇新文章上了,叫做積累與雜貨鋪一以及相關(guān)教程的規(guī)范與相關(guān)中文學(xué)習(xí)大本營中文文檔簡 做一個(gè)搬運(yùn)工,希望自己能努力學(xué)習(xí),也希望大神們的東西能讓更多的人看到 不斷更新 更新日志:2017.10.13 新增了網(wǎng)絡(luò)安全分類,整理了排版布局...
摘要:開發(fā)教程步步為營,掌握基礎(chǔ)技能發(fā)布機(jī)器學(xué)習(xí)速成課程為了幫助更多的人了解與學(xué)習(xí)機(jī)器學(xué)習(xí)相關(guān)的知識(shí)技能,發(fā)布了人工智能學(xué)習(xí)網(wǎng)站。更多相關(guān)內(nèi)容參考數(shù)據(jù)科學(xué)與機(jī)器學(xué)習(xí)實(shí)戰(zhàn)手冊。 showImg(https://segmentfault.com/img/remote/1460000013586587); 前端每周清單專注前端領(lǐng)域內(nèi)容,以對外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點(diǎn);分為新聞熱...
閱讀 1825·2023-04-26 02:32
閱讀 573·2021-11-18 13:12
閱讀 2457·2021-10-20 13:48
閱讀 2526·2021-10-14 09:43
閱讀 3837·2021-10-11 10:58
閱讀 3503·2021-09-30 10:00
閱讀 2940·2019-08-30 15:53
閱讀 3495·2019-08-30 15:53