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