<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                {% raw %} # Flask-WTF **Flask-WTF** 提供了簡單地 [WTForms](http://wtforms.simplecodes.com/docs/) 的集成。 ## 功能 * 集成 wtforms。 * 帶有 csrf 令牌的安全表單。 * 全局的 csrf 保護。 * 支持驗證碼(Recaptcha)。 * 與 Flask-Uploads 一起支持文件上傳。 * 國際化集成。 # 安裝 該部分文檔涵蓋了 Flask-WTF 安裝。使用任何軟件包的第一步即是正確安裝它。 ## Distribute & Pip 用 [pip](http://www.pip-installer.org/) 安裝 Flask-WTF 是十分簡單的: ``` $ pip install Flask-WTF ``` 或者,使用 [easy_install](http://pypi.python.org/pypi/setuptools): ``` $ easy_install Flask-WTF ``` 但是,你真的 [不應該這樣做](https://python-packaging-user-guide.readthedocs.org/en/latest/technical.html#pip-vs-easy-install)。 ## 獲取源代碼 Flask-WTF 在 GitHub 上活躍開發,代碼在 GitHub 上 [始終可用](https://github.com/lepture/flask-wtf)。 你也可以克隆公開倉庫: ``` git clone git://github.com/lepture/flask-wtf.git ``` 下載 [tarball](https://github.com/lepture/flask-wtf/tarball/master): ``` $ curl -OL https://github.com/lepture/flask-wtf/tarball/master ``` 或者,下載 [zipball](https://github.com/lepture/flask-wtf/zipball/master): ``` $ curl -OL https://github.com/lepture/flask-wtf/zipball/master ``` 當你有一份源碼的副本后,你很容易地就可以把它嵌入到你的 Python 包中,或是安裝到 site-packages: ``` $ python setup.py install ``` # 快讀入門 急于上手?本頁對 Flask-WTF 給出了一個詳盡的介紹。假設你已經安裝了 Flask-WTF,如果還未安裝的話,請先瀏覽 [_安裝_](install.html)。 ## 創建表單 Flask-WTF 提供了對 WTForms 的集成。例如: ``` from flask_wtf import Form from wtforms import StringField from wtforms.validators import DataRequired class MyForm(Form): name = StringField('name', validators=[DataRequired()]) ``` Note 從 0.9.0 版本開始,Flask-WTF 將不會從 wtforms 中導入任何的內容,用戶必須自己從 wtforms 中導入字段。 另外,隱藏的 CSRF 令牌會被自動地創建。你可以在模板這樣地渲染它: ``` <form method="POST" action="/"> {{ form.csrf_token }} {{ form.name.label }} {{ form.name(size=20) }} <input type="submit" value="Go"> </form> ``` 盡管如此,為了創建有效的 XHTML/HTML, Form 類有一個 hidden_tag 方法, 它在一個隱藏的 DIV 標簽中渲染任何隱藏的字段,包括 CSRF 字段: ``` <form method="POST" action="/"> {{ form.hidden_tag() }} {{ form.name.label }} {{ form.name(size=20) }} <input type="submit" value="Go"> </form> ``` ## 驗證表單 在你的視圖處理程序中驗證請求: ``` @app.route('/submit', methods=('GET', 'POST')) def submit(): form = MyForm() if form.validate_on_submit(): return redirect('/success') return render_template('submit.html', form=form) ``` 注意你不需要把 `request.form` 傳給 Flask-WTF;Flask-WTF 會自動加載。便捷的方法 `validate_on_submit` 將會檢查是否是一個 POST 請求并且請求是否有效。 閱讀 [_創建表單_](form.html) 學習更多的關于表單的技巧。 # 創建表單 這部分文檔涉及表單(Form)信息。 ## 安全表單 無需任何配置,[`Form`](api.html#flask_wtf.Form "flask_wtf.Form") 是一個帶有 CSRF 保護的并且會話安全的表單。我們鼓勵你什么都不做。 但是如果你想要禁用 CSRF 保護,你可以這樣: ``` form = Form(csrf_enabled=False) ``` 如果你想要全局禁用 CSRF 保護,你真的不應該這樣做。但是你要堅持這樣做的話,你可以在配置中這樣寫: ``` WTF_CSRF_ENABLED = False ``` 為了生成 CSRF 令牌,你必須有一個密鑰,這通常與你的 Flask 應用密鑰一致。如果你想使用不同的密鑰,可在配置中指定: ``` WTF_CSRF_SECRET_KEY = 'a random string' ``` ## 文件上傳 Flask-WTF 提供 [`FileField`](api.html#flask_wtf.file.FileField "flask_wtf.file.FileField") 來處理文件上傳,它在表單提交后,自動從 `flask.request.files` 中抽取數據。[`FileField`](api.html#flask_wtf.file.FileField "flask_wtf.file.FileField") 的 `data` 屬性是一個 Werkzeug FileStorage 實例。 例如: ``` from werkzeug import secure_filename from flask_wtf.file import FileField class PhotoForm(Form): photo = FileField('Your photo') @app.route('/upload/', methods=('GET', 'POST')) def upload(): form = PhotoForm() if form.validate_on_submit(): filename = secure_filename(form.photo.data.filename) form.photo.data.save('uploads/' + filename) else: filename = None return render_template('upload.html', form=form, filename=filename) ``` Note 記得把你的 HTML 表單的 `enctype` 設置成 `multipart/form-data`,既是: ``` <form action="/upload/" method="POST" enctype="multipart/form-data"> .... </form> ``` 此外,Flask-WTF 支持文件上傳的驗證。提供了 [`FileRequired`](api.html#flask_wtf.file.FileRequired "flask_wtf.file.FileRequired") 和 [`FileAllowed`](api.html#flask_wtf.file.FileAllowed "flask_wtf.file.FileAllowed")。 [`FileAllowed`](api.html#flask_wtf.file.FileAllowed "flask_wtf.file.FileAllowed") 能夠很好地和 Flask-Uploads 一起協同工作, 例如: ``` from flask.ext.uploads import UploadSet, IMAGES from flask_wtf import Form from flask_wtf.file import FileField, FileAllowed, FileRequired images = UploadSet('images', IMAGES) class UploadForm(Form): upload = FileField('image', validators=[ FileRequired(), FileAllowed(images, 'Images only!') ]) ``` 也能在沒有 Flask-Uploads 下挑大梁。這時候你需要向 [`FileAllowed`](api.html#flask_wtf.file.FileAllowed "flask_wtf.file.FileAllowed") 傳入擴展名即可: ``` class UploadForm(Form): upload = FileField('image', validators=[ FileRequired(), FileAllowed(['jpg', 'png'], 'Images only!') ]) ``` ## HTML5 控件 Note 自 wtforms 1.0.5 版本開始,wtforms 就內嵌了 HTML5 控件和字段。如果可能的話,你可以考慮從 wtforms 中導入它們。 我們將會在 0.9.3 版本后移除 html5 模塊。 你可以從 `wtforms` 中導入一些 HTML5 控件: ``` from wtforms.fields.html5 import URLField from wtforms.validators import url class LinkForm(Form): url = URLField(validators=[url()]) ``` ## 驗證碼 Flask-WTF 通過 `RecaptchaField` 也提供對驗證碼的支持: ``` from flask_wtf import Form, RecaptchaField from wtforms import TextField class SignupForm(Form): username = TextField('Username') recaptcha = RecaptchaField() ``` 這伴隨著諸多配置,你需要逐一地配置它們。 | | | | --- | --- | | RECAPTCHA_PUBLIC_KEY | **必須** 公鑰 | | RECAPTCHA_PRIVATE_KEY | **必須** 私鑰 | | RECAPTCHA_API_SERVER | **可選** 驗證碼 API 服務器 | | RECAPTCHA_PARAMETERS | **可選** 一個 JavaScript(api.js)參數的字典 | | RECAPTCHA_DATA_ATTRS | **可選** 一個數據屬性項列表 [https://developers.google.com/recaptcha/docs/display](https://developers.google.com/recaptcha/docs/display) | RECAPTCHA_PARAMETERS 和 RECAPTCHA_DATA_ATTRS 的示例: ``` RECAPTCHA_PARAMETERS = {'hl': 'zh', 'render': 'explicit'} RECAPTCHA_DATA_ATTRS = {'theme': 'dark'} ``` 對于應用測試時,如果 `app.testing` 為 `True` ,考慮到方便測試,Recaptcha 字段總是有效的。 在模板中很容易添加 Recaptcha 字段: ``` <form action="/" method="post"> {{ form.username }} {{ form.recaptcha }} </form> ``` 我們為你提供了例子: [recaptcha@github](https://github.com/lepture/flask-wtf/tree/master/examples/recaptcha)。 # CSRF 保護 這部分文檔介紹了 CSRF 保護。 ## 為什么需要 CSRF? Flask-WTF 表單保護你免受 CSRF 威脅,你不需要有任何擔心。盡管如此,如果你有不包含表單的視圖,那么它們仍需要保護。 例如,由 AJAX 發送的 POST 請求,然而它背后并沒有表單。在 Flask-WTF 0.9.0 以前的版本你無法獲得 CSRF 令牌。這是為什么我們要實現 CSRF。 ## 實現 為了能夠讓所有的視圖函數受到 CSRF 保護,你需要開啟 [`CsrfProtect`](api.html#flask_wtf.csrf.CsrfProtect "flask_wtf.csrf.CsrfProtect") 模塊: ``` from flask_wtf.csrf import CsrfProtect CsrfProtect(app) ``` 像任何其它的 Flask 擴展一樣,你可以惰性加載它: ``` from flask_wtf.csrf import CsrfProtect csrf = CsrfProtect() def create_app(): app = Flask(__name__) csrf.init_app(app) ``` Note 你需要為 CSRF 保護設置一個秘鑰。通常下,同 Flask 應用的 SECRET_KEY 是一樣的。 如果模板中存在表單,你不需要做任何事情。與之前一樣: ``` <form method="post" action="/"> {{ form.csrf_token }} </form> ``` 但是如果模板中沒有表單,你仍然需要一個 CSRF 令牌: ``` <form method="post" action="/"> <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" /> </form> ``` 無論何時未通過 CSRF 驗證,都會返回 400 響應。你可以自定義這個錯誤響應: ``` @csrf.error_handler def csrf_error(reason): return render_template('csrf_error.html', reason=reason), 400 ``` 我們強烈建議你對所有視圖啟用 CSRF 保護。但也提供了某些視圖函數不需要保護的裝飾器: ``` @csrf.exempt @app.route('/foo', methods=('GET', 'POST')) def my_handler(): # ... return 'ok' ``` 默認情況下你也可以在所有的視圖中禁用 CSRF 保護,通過設置 `WTF_CSRF_CHECK_DEFAULT` 為 `False`,僅僅當你需要的時候選擇調用 `csrf.protect()`。這也能夠讓你在檢查 CSRF 令牌前做一些預先處理: ``` @app.before_request def check_csrf(): if not is_oauth(request): csrf.protect() ``` ## AJAX 不需要表單,通過 AJAX 發送 POST 請求成為可能。0.9.0 版本后這個功能變成可用的。 假設你已經使用了 `CsrfProtect(app)`,你可以通過 `{{ csrf_token() }}` 獲取 CSRF 令牌。這個方法在每個模板中都可以使用,你并不需要擔心在沒有表單時如何渲染 CSRF 令牌字段。 我們推薦的方式是在 `<meta>` 標簽中渲染 CSRF 令牌: ``` <meta name="csrf-token" content="{{ csrf_token() }}"> ``` 在 `<script>` 標簽中渲染同樣可行: ``` <script type="text/javascript"> var csrftoken = "{{ csrf_token() }}" </script> ``` 下面的例子采用了在 `<meta>` 標簽渲染的方式, 在 `<script>` 中渲染會更簡單,你無須擔心沒有相應的例子。 無論何時你發送 AJAX POST 請求,為其添加 `X-CSRFToken` 頭: ``` var csrftoken = $('meta[name=csrf-token]').attr('content') $.ajaxSetup({ beforeSend: function(xhr, settings) { if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken) } } }) ``` ## 故障排除 當你定義你的表單的時候,如果犯了 [`這個錯誤`_](#id4) : 從 `wtforms` 中導入 `Form` 而不是從 `flask.ext.wtf` 中導入,CSRF 保護的大部分功能都能工作(除了 `form.validate_on_submit()`),但是 CSRF 保護將會發生異常。在提交表單的時候,你將會得到 `Bad Request`/`CSRF token missing or incorrect` 錯誤。這個錯誤的出現就是因為你的導入錯誤,而不是你的配置問題。 # 配置 這里是所有配置的全表。 ## 表單和 CSRF Flask-WTF 完整的配置清單。通常,你不必配置它們。默認的配置就能正常工作。 | | | | --- | --- | | WTF_CSRF_ENABLED | 禁用/開啟表單的 CSRF 保護。默認是開啟。 | | WTF_CSRF_CHECK_DEFAULT | 默認下啟用 CSRF 檢查針對所有的視圖。 默認值是 True。 | | WTF_I18N_ENABLED | 禁用/開啟 I18N 支持。需要和 Flask-Babel 配合一起使用。默認是開啟。 | | WTF_CSRF_HEADERS | 需要檢驗的 CSRF 令牌 HTTP 頭。默認是 **[‘X-CSRFToken’, ‘X-CSRF-Token’]** | | WTF_CSRF_SECRET_KEY | 一個隨機字符串生成 CSRF 令牌。 默認同 SECRET_KEY 一樣。 | | WTF_CSRF_TIME_LIMIT | CSRF 令牌過期時間。默認是 **3600** 秒。 | | WTF_CSRF_SSL_STRICT | 使用 SSL 時進行嚴格保護。這會檢查 HTTP Referrer, 驗證是否同源。默認為 True 。 | | WTF_CSRF_METHODS | 使用 CSRF 保護的 HTTP 方法。默認是 **[‘POST’, ‘PUT’, ‘PATCH’]** | | WTF_HIDDEN_TAG | 隱藏的 HTML 標簽包裝的名稱。 默認是 **div** | | WTF_HIDDEN_TAG_ATTRS | 隱藏的 HTML 標簽包裝的標簽屬性。 默認是 **{‘style’: ‘display:none;’}** | ## 驗證碼 你已經在 [_驗證碼_](form.html#recaptcha) 中了解了這些配置選項。該表為了方便速查。 | | | | --- | --- | | RECAPTCHA_USE_SSL | 允許/禁用 Recaptcha 使用 SSL。默認是 False。 | | RECAPTCHA_PUBLIC_KEY | **必須** 公鑰。 | | RECAPTCHA_PRIVATE_KEY | **必須** 私鑰。 | | RECAPTCHA_OPTIONS | **可選** 配置選項的字典。 [https://www.google.com/recaptcha/admin/create](https://www.google.com/recaptcha/admin/create) | # 開發者接口 該部分文檔涵蓋了 Flask-WTF 的全部接口。 ## 表單和字段 `class flask_wtf.Form(formdata=<class flask_wtf.form._Auto at 0x10627ed50>, obj=None, prefix='', csrf_context=None, secret_key=None, csrf_enabled=None, *args, **kwargs)` Flask-specific subclass of WTForms **SecureForm** class. If formdata is not specified, this will use flask.request.form. Explicitly pass formdata = None to prevent this. Parameters: * **csrf_context** – a session or dict-like object to use when making CSRF tokens. Default: flask.session. * **secret_key** – a secret key for building CSRF tokens. If this isn’t specified, the form will take the first of these that is defined: * SECRET_KEY attribute on this class * WTF_CSRF_SECRET_KEY config of flask app * SECRET_KEY config of flask app * session secret key * **csrf_enabled** – whether to use CSRF protection. If False, all csrf behavior is suppressed. Default: WTF_CSRF_ENABLED config value `hidden_tag(*fields)` Wraps hidden fields in a hidden DIV tag, in order to keep XHTML compliance. New in version 0.3. Parameters: **fields** – list of hidden field names. If not provided will render all hidden fields, including the CSRF field. `is_submitted()` Checks if form has been submitted. The default case is if the HTTP method is **PUT** or **POST**. `validate_csrf_data(data)` Check if the csrf data is valid. Parameters: **data** – the csrf string to be validated. `validate_on_submit()` Checks if form has been submitted and if so runs validate. This is a shortcut, equivalent to `form.is_submitted() and form.validate()` `class flask_wtf.RecaptchaField(label='', validators=None, **kwargs)` `class flask_wtf.Recaptcha(message=None)` Validates a ReCaptcha. `class flask_wtf.RecaptchaWidget` `class flask_wtf.file.FileField(label=None, validators=None, filters=(), description=u'', id=None, default=None, widget=None, _form=None, _name=None, _prefix=u'', _translations=None, _meta=None)` Werkzeug-aware subclass of **wtforms.FileField** Provides a `has_file()` method to check if its data is a FileStorage instance with an actual file. `has_file()` Return True iff self.data is a FileStorage with file data `class flask_wtf.file.FileAllowed(upload_set, message=None)` Validates that the uploaded file is allowed by the given Flask-Uploads UploadSet. Parameters: * **upload_set** – A list/tuple of extention names or an instance of `flask.ext.uploads.UploadSet` * **message** – error message You can also use the synonym **file_allowed**. `class flask_wtf.file.FileRequired(message=None)` Validates that field has a file. Parameters: **message** – error message You can also use the synonym **file_required**. `class flask_wtf.html5.SearchInput(input_type=None)` Renders an input with type “search”. `class flask_wtf.html5.SearchField(label=None, validators=None, filters=(), description=u'', id=None, default=None, widget=None, _form=None, _name=None, _prefix=u'', _translations=None, _meta=None)` Represents an `<input type="search">`. `class flask_wtf.html5.URLInput(input_type=None)` Renders an input with type “url”. `class flask_wtf.html5.URLField(label=None, validators=None, filters=(), description=u'', id=None, default=None, widget=None, _form=None, _name=None, _prefix=u'', _translations=None, _meta=None)` Represents an `<input type="url">`. `class flask_wtf.html5.EmailInput(input_type=None)` Renders an input with type “email”. `class flask_wtf.html5.EmailField(label=None, validators=None, filters=(), description=u'', id=None, default=None, widget=None, _form=None, _name=None, _prefix=u'', _translations=None, _meta=None)` Represents an `<input type="email">`. `class flask_wtf.html5.TelInput(input_type=None)` Renders an input with type “tel”. `class flask_wtf.html5.TelField(label=None, validators=None, filters=(), description=u'', id=None, default=None, widget=None, _form=None, _name=None, _prefix=u'', _translations=None, _meta=None)` Represents an `<input type="tel">`. `class flask_wtf.html5.NumberInput(step=None)` Renders an input with type “number”. `class flask_wtf.html5.IntegerField(label=None, validators=None, **kwargs)` Represents an `<input type="number">`. `class flask_wtf.html5.DecimalField(label=None, validators=None, places=<unset value>, rounding=None, **kwargs)` Represents an `<input type="number">`. `class flask_wtf.html5.RangeInput(step=None)` Renders an input with type “range”. `class flask_wtf.html5.IntegerRangeField(label=None, validators=None, **kwargs)` Represents an `<input type="range">`. `class flask_wtf.html5.DecimalRangeField(label=None, validators=None, places=<unset value>, rounding=None, **kwargs)` Represents an `<input type="range">`. ## CSRF 保護 `class flask_wtf.csrf.CsrfProtect(app=None)` Enable csrf protect for Flask. Register it with: ``` app = Flask(__name__) CsrfProtect(app) ``` And in the templates, add the token input: ``` <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/> ``` If you need to send the token via AJAX, and there is no form: ``` <meta name="csrf_token" content="{{ csrf_token() }}" /> ``` You can grab the csrf token with JavaScript, and send the token together. `error_handler(view)` A decorator that set the error response handler. It accepts one parameter `reason`: ``` @csrf.error_handler def csrf_error(reason): return render_template('error.html', reason=reason) ``` By default, it will return a 400 response. `exempt(view)` A decorator that can exclude a view from csrf protection. Remember to put the decorator above the `route`: ``` csrf = CsrfProtect(app) @csrf.exempt @app.route('/some-view', methods=['POST']) def some_view(): return ``` `flask_wtf.csrf.generate_csrf(secret_key=None, time_limit=None)` Generate csrf token code. Parameters: * **secret_key** – A secret key for mixing in the token, default is Flask.secret_key. * **time_limit** – Token valid in the time limit, default is 3600s. `flask_wtf.csrf.validate_csrf(data, secret_key=None, time_limit=None)` Check if the given data is a valid csrf token. Parameters: * **data** – The csrf token value to be checked. * **secret_key** – A secret key for mixing in the token, default is Flask.secret_key. * **time_limit** – Check if the csrf token is expired. default is True. # 升級到新版本 Flask-WTF 像其它軟件一樣隨時間推移而改動。大多數改動是良性的,就是當你升級到新版而無需做出任何改動的良性。 盡管如此,每隔一段時間,就會有需要你對代碼做出改動或是允許你改善你自己的代碼質量來從 Flask-WTF 新特性獲益的改動。 本節文檔列舉所有 Flask-WTF 版本中的所有變更以及如何進行無痛苦的升級。 如果你想用 pip 命令升級 Flask-WTF,確保傳遞 -U 參數: ``` $ pip install -U Flask-WTF ``` ## 版本 0.9.0 移除 wtforms 的導入是一個重大的改變,這可能會給你帶來許多痛苦,但這些導入項難以維護。你需要從原始的 WTForms 中導入 `Fields` ,而不是從 Flask-WTF 中導入: ``` from wtforms import TextField ``` 配置選項 `CSRF_ENABLED` 改為 `WTF_CSRF_ENABLED` 。如果你沒有設置任何配置選項,那么你無須做任何變動。 這個版本有很多的特色功能,如果你不需要他們,他們不會對你的任何代碼有影響。 # Flask-WTF 更新歷史 Flask-WTF 的所有發布版本的變更列表。 ## Version 0.12 Released 2015/07/09 * Abstract protect_csrf() into a separate method * Update reCAPTCHA configuration * Fix reCAPTCHA error handle ## Version 0.11 Released 2015/01/21 * Use the new reCAPTCHA API via [#164](https://github.com/lepture/flask-wtf/pull/164). ## Version 0.10.3 Released 2014/11/16 * Add configuration: WTF_CSRF_HEADERS via [#159](https://github.com/lepture/flask-wtf/pull/159). * Support customize hidden tags via [#150](https://github.com/lepture/flask-wtf/pull/150). * And many more bug fixes ## Version 0.10.2 Released 2014/09/03 * Update translation for reCaptcha via [#146](https://github.com/lepture/flask-wtf/pull/146). ## Version 0.10.1 Released 2014/08/26 * Update RECAPTCHA API SERVER URL via [#145](https://github.com/lepture/flask-wtf/pull/145). * Update requirement Werkzeug>=0.9.5 * Fix CsrfProtect exempt for blueprints via [#143](https://github.com/lepture/flask-wtf/pull/143). ## Version 0.10.0 Released 2014/07/16 * Add configuration: WTF_CSRF_METHODS * Support WTForms 2.0 now * Fix csrf validation without time limit (time_limit=False) * CSRF exempt supports blueprint [#111](https://github.com/lepture/flask-wtf/issues/111). ## Version 0.9.5 Released 2014/03/21 * `csrf_token` for all template types [#112](https://github.com/lepture/flask-wtf/issues/112). * Make FileRequired a subclass of InputRequired [#108](https://github.com/lepture/flask-wtf/issues/108). ## Version 0.9.4 Released 2013/12/20 * Bugfix for csrf module when form has a prefix * Compatible support for wtforms2 * Remove file API for FileField ## Version 0.9.3 Released 2013/10/02 * Fix validation of recaptcha when app in testing mode [#89](https://github.com/lepture/flask-wtf/issues/89). * Bugfix for csrf module [#91](https://github.com/lepture/flask-wtf/issues/91) ## Version 0.9.2 Released 2013/9/11 * Upgrade wtforms to 1.0.5. * No lazy string for i18n [#77](https://github.com/lepture/flask-wtf/issues/77). * No DateInput widget in html5 [#81](https://github.com/lepture/flask-wtf/issues/81). * PUT and PATCH for CSRF [#86](https://github.com/lepture/flask-wtf/issues/86). ## Version 0.9.1 Released 2013/8/21 This is a patch version for backward compitable for Flask<0.10 [#82](https://github.com/lepture/flask-wtf/issues/82). ## Version 0.9.0 Released 2013/8/15 * Add i18n support (issue #65) * Use default html5 widgets and fields provided by wtforms * Python 3.3+ support * Redesign form, replace SessionSecureForm * CSRF protection solution * Drop wtforms imports * Fix recaptcha i18n support * Fix recaptcha validator for python 3 * More test cases, it’s 90%+ coverage now * Redesign documentation ## Version 0.8.4 Released 2013/3/28 * Recaptcha Validator now returns provided message (issue #66) * Minor doc fixes * Fixed issue with tests barking because of nose/multiprocessing issue. ## Version 0.8.3 Released 2013/3/13 * Update documentation to indicate pending deprecation of WTForms namespace facade * PEP8 fixes (issue #64) * Fix Recaptcha widget (issue #49) ## Version 0.8.2 and prior Initial development by Dan Jacob and Ron Duplain. 0.8.2 and prior there was not a change log. # 作者 Flask-WTF 是由 Dan Jacob 創建,現在是由 Hsiaoming Yang 維護。 ## 貢獻者 貢獻過補丁和建議的人們: * Dan Jacob * Ron DuPlain * Daniel Lepage * Anthony Ford * Hsiaoming Yang 更多的貢獻者可以在 [GitHub](http://github.com/lepture/flask-wtf/contributors) 上找到。 # BSD 許可證 Copyright (c) 2010 by Dan Jacob. Copyright (c) 2013 - 2014 by Hsiaoming Yang. Some rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. {% endraw %}
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看