pax_global_header00006660000000000000000000000064133063267450014523gustar00rootroot0000000000000052 comment=7152845801e88ab6a9c7d719b73d41bef6464b5d wtforms-2.2.1/000077500000000000000000000000001330632674500132265ustar00rootroot00000000000000wtforms-2.2.1/.gitignore000066400000000000000000000003061330632674500152150ustar00rootroot00000000000000# File extensions *.pyc *.pyo .*.swp .DS_Store # Extra Files MANIFEST WTForms.egg-info .coverage .coveralls.yml # Directories build/ dist/ docs/_build docs/html env/ .pytest_cache/ .tox/ htmlcov/ wtforms-2.2.1/.travis.yml000066400000000000000000000007771330632674500153520ustar00rootroot00000000000000os: linux sudo: false language: python python: - 3.6 - 3.5 - 3.4 - 3.3 - 2.7 - 2.6 - nightly - pypy3 env: - TOXENV=py matrix: allow_failures: - python: 2.6 - python: 3.3 - python: nightly - python: pypy3 fast_finish: true install: - pip install tox script: - tox after_success: - pip install coveralls - coverage combine - coverage report - coveralls cache: - pip branches: only: - master - /^.*-maintenance$/ notifications: email: false wtforms-2.2.1/AUTHORS.rst000066400000000000000000000004421330632674500151050ustar00rootroot00000000000000WTForms is developed and maintained by the WTForms team and community contributors. It was originally created in 2008 by James Crasta and Thomas Johansson. The core maintainers are: - David Lord (davidism) A full list of contributors is available from git with:: git shortlog -sne wtforms-2.2.1/CHANGES.rst000066400000000000000000000342571330632674500150430ustar00rootroot00000000000000.. currentmodule:: wtforms WTForms Changelog ================= Version 2.2.1 ------------- Released on June 7th, 2018 - :class:`~fields.StringField` only sets ``data = ''` when form data is empty and an initial value was not provided. This fixes an issue where the default value wasn't rendered with the initial form. (`#291`_, `#355`_, `#401`_) .. _#291: https://github.com/wtforms/wtforms/issues/291 .. _#355: https://github.com/wtforms/wtforms/pull/355 .. _#401: https://github.com/wtforms/wtforms/issues/401 Version 2.2 ----------- Released on June 2nd, 2018 - Merged new and updated translations from the community. - Passing ``data_`` args to render a field converts all the underscores to hyphens when rendering the HTML attribute, not just the first one. ``data_foo_bar`` becomes ``data-foo-bar``. (`#248`_) - The :class:`~validators.UUID` validator uses the :class:`uuid.UUID` class instead of a regex. (`#251`_) - :class:`~fields.SelectField` copies the list of ``choices`` passed to it so modifying an instance's choices will not modify the global form definition. (`#286`_) - Fields call :meth:`~fields.Field.process_formdata` even if the raw data is empty. (`#280`_) - Added a :class:`~fields.MultipleFileField` to handle a multi-file input. :class:`~fields.FileField` continues to handle only one value. The underlying :class:`~widgets.FileInput` widget gained a ``multiple`` argument. (`#281`_) - :class:`~fields.SelectField` choices can contain HTML (MarkupSafe ``Markup`` object or equivalent API) and will be rendered properly. (`#302`_) - :class:`~fields.TimeField` and :class:`html5.TimeField ` were added. (`#254`_) - Improved :class:`~validators.Email`. Note that it is still unreasonable to validate all emails with a regex and you should prefer validating by actually sending an email. (`#294`_) - Widgets render the ``required`` attribute when using a validator that provides the ``'required'`` flag, such as :class:`~validators.DataRequired`. (`#361`_) - Fix a compatibility issue with SQLAlchemy 2.1 that caused :class:`~ext.sqlalchemy.fields.QuerySelectField` to fail with ``ValueError: too many values to unpack``. (`#391`_) .. _#248: https://github.com/wtforms/wtforms/pull/248 .. _#251: https://github.com/wtforms/wtforms/pull/251 .. _#254: https://github.com/wtforms/wtforms/pull/254 .. _#280: https://github.com/wtforms/wtforms/pull/280 .. _#281: https://github.com/wtforms/wtforms/pull/281 .. _#286: https://github.com/wtforms/wtforms/pull/286 .. _#294: https://github.com/wtforms/wtforms/pull/294 .. _#302: https://github.com/wtforms/wtforms/pull/302 .. _#361: https://github.com/wtforms/wtforms/pull/361 .. _#391: https://github.com/wtforms/wtforms/pull/391 Version 2.1 ----------- Released December 15, 2015 - Added ``render_kw`` to allow default rendering time options. - Updated / added a number of localizations - Updated docs - Allow widgets to set flags Version 2.0.2 ------------- Released January 18, 2015 - Added more localizations and updated some. - Validators for email and URL can validate IDNA-encoded domain names and new TLDs - Better ``DeprecationWarnings`` - Support localization files in ``/usr/share/locale`` (for distro packaging) Version 2.0.1 ------------- Released July 1, 2014 - Update wheel install to conditionally install ordereddict for python 2.6. - Doc improvements Version 2.0 ----------- Released May 20, 2014 - Add new ``class Meta`` paradigm for much more powerful customization of WTForms. - Move i18n into core. Deprecate ``wtforms.ext.i18n``. - Move CSRF into core. Deprecate ``wtforms.ext.csrf``. - Fix issue rendering SelectFields with ``value=True`` - Make ``DecimalField`` able to use babel locale-based number formatting. - Drop Python 3.2 support (Python3 support for 3.3+ only) - passing ``attr=False`` to WTForms widgets causes the value to be ignored. - ``Unique`` validator in ``wtforms.ext.sqlalchemy`` has been removed. Version 1.0.5 ------------- Released September 10, 2013 - Fix a bug in validators which causes translations to happen once then clobber any future translations. - ``ext.sqlalchemy`` / ``ext.appengine``: minor cleanups / deprecation. - Allow blank string and the string ``false`` to be considered false values for ``BooleanField`` (configurable). This is technically a breaking change, but it is not likey to affect the majority of users adversely. - ``ext.i18n`` form allows passing ``LANGUAGES`` to the constructor. Version 1.0.4 ------------- Released April 28, 2013 - Add widgets and field implementations for HTML5 specialty input types. - ``ext.appengine``: Add NDB support. - Add translations: Korean, Traditional Chinese Version 1.0.3 ------------- Released January 24, 2013 - Tests complete in python 3.2/3.3. - Localization for ru, fr. - Minor fixes in documentation for clarity. - ``FieldList`` now can take validators on the entire ``FieldList``. - ``ext.sqlalchemy`` model_form: * Fix issue with ``QuerySelectField`` * Fix issue in ``ColumnDefault`` conversion * Support ``Enum`` type - Field class now allows traversal in Django 1.4 templates. Version 1.0.2 ------------- Released August 24, 2012 - We now support Python 2.x and 3.x on the same codebase, thanks to a lot of hard work by Vinay Sajip. - Add in ability to convert relationships to ``ext.sqlalchemy`` ``model_form`` - Built-in localizations for more languages - Validator cleanup: * Distinguish ``Required`` validator into ``InputRequired`` and ``DataRequired`` * Better IP address validation, including IPv6 support. * ``AnyOf`` / ``NoneOf`` now work properly formatting other datatypes than strings. * ``Optional`` validator can optionally pass through whitespace. Version 1.0.1 ------------- Released February 29, 2012 - Fixed issues related to building for python 3 and python pre-releases. - Add ``object_data`` to fields to get at the originally passed data. Version 1.0 ----------- Released February 28, 2012 - Output HTML5 compact syntax by default. - Substantial code reorg, cleanup, and test improvements - Added ``ext.csrf`` for a way to implement CSRF protection - ``ext.sqlalchemy``: * Support ``PGInet``, ``MACADDR``, and ``UUID`` field conversion * Support callable defaults - ``ext.appengine``: * model_form now supports generating forms with the same ordering as model. * ReferencePropertyField now gets get_label like the other ORM fields - Add localization support for WTForms built-in messages - Python 3 support (via 2to3) - Minor changes/fixes: * An empty label string can be specified on fields if desired * ``Option`` widget can now take kwargs customization * Field subclasses can provide default validators as a class property * ``DateTimeField`` can take time in microseconds * Numeric fields all set ``.data`` to ``None`` on coercion error for consistency. Version 0.6.3 ------------- Released April 24, 2011 - Documentation: Substantial documentation improvements, including adding Crash Course as a sphinx document. - ``ext.django``: ``QuerySetSelectField`` (and ``ModelSelectField``) now accept ``get_label`` similar to sqlalchemy equivalents. - ``ext.appengine`` * model_form fixes: ``FloatField`` (#50), ``TimeField``, ``DateTimeField`` (#55) * ``ReferencePropertyField``: now properly stores model object, not key. (#48) Version 0.6.2 ------------- Released January 22, 2011 - Bug Fixes: * ``ext.appengine``: various field fixes (#34, #48), ``model_form`` changes (#41) * Fix issue in ``Optional`` with non-string input. * Make numeric fields more consistent. - Tests: Improve test coverage substantially. Version 0.6.1 ------------- Released September 17th, 2010 - Bug Fixes: * ``ext.appengine ReferencePropertyField`` (#36, #37) * dateutil fields: render issue (r419), and consistency issue (#35) * Optional validator failed when raw_data was absent (r418) - Documentation: docs now mention HTML escaping functionality (#38) - Add preliminary support for providing a translations object that can translate built-in validation and coercion errors (#32) Version 0.6 ----------- Released April 25th, 2010. - Widgets: * HTML is now marked as safe (using ``__html__``) so that compatible templating engines will not auto-escape it. - Fields: * ``Field._default`` is now ``Field.default``. * All fields now have a ``raw_data`` property. * Fields which are select fields (including those in ``.ext``) can be iterated to produce options, and have an ``option_widget`` kwarg. * Minor bugfixes and cleanup in ``FieldList``, ``Select(Multiple)Field``, ``QuerySelectField`` to address behavioral consistency. * Added ``FloatField``, based on ``IntegerField``. - Extensions: * ext.appengine now supports FloatProperty and GeoPtProperty. * ext.sqlalchemy QueryMultipleSelectField changed to QuerySelectMultipleField. Version 0.5 ----------- Released February 13th, 2010. - Added a ``BaseForm`` class which provides the core processing and validation functionality of ``Form`` without requiring declarative subclassing. - Fields: * Field labels now default to a humanized field name. * Fields now have a ``short_name`` property which is the un-prefixed name. * ``DecimalField`` now rounds values for display without float coercion. See docs for details on how to format decimals. - Extensions: * ``ext.sqlalchemy.fields`` now has an additional ``QuerySelectMultipleField``, and all fields can now support multiple-column primary keys. * ``ext.sqlalchemy.orm`` contains tools for making forms from ORM models. * Added ``ext.dateutil`` for flexible date-time parsing. * Added ``ext.appengine`` contributed by Rodrigo Moraes. - Added AnyOf and NoneOf validators. Version 0.4 ----------- Released October 10th, 2009. - Fields have much greater control over input processing. Filters have been added to implement a simple way to transform input data. - Added fields that encapsulate advanced data structures such as dynamic lists or child forms for more powerful field composing. - Fields now use widgets for rendering. - All built-in validators have been converted to classes to clean up the code. - ``Form.auto_populate`` and ``Field.populate`` were renamed to ``populate_obj`` to clarify that they populate another object, not the Form or Field. This is an API breaking change. - Dropped support for Python 2.3. Version 0.3.1 ------------- Released January 24th, 2009. - Several fixes were made to the code and tests to make WTForms compatible with Python 2.3/2.4. - Form's properties can now be accessed via dictionary-style access such as ``form['author']``. This also has the intended effect of making variable lookups in Django templates more reliable. - Form and Field construction changes: Form now uses a metaclass to handle creating its ``_unbound_fields`` property, and Field construction now gives an instance of the new ``UnboundField`` class instead of using a partial function application. These are both internal changes and do not change the API. Version 0.3 ----------- Released January 18th, 2009. - Validation overhaul: Fields are now responsible for their own validation, instead of mostly relying on ``Form``. There are also new ``pre_validate`` and ``post_validate`` hooks on subfields, adding a great deal of flexibility when dealing with field-level validation. Note that this is an API breaking change if you have any subfields that override ``Field.validate``. These will need to be updated to use the new hooks. - Changes in how ``process_data`` and ``process_formdata`` are called: * ``process_data`` no longer accepts the ``has_formdata`` parameter. * At form instantiation time, ``process_data`` will be called only once for each field. If a model object is provided which contains the property, then this value is used. Otherwise, a keyword argument if specified is used. Failing that, the field's default value is used. * If any form data is sent, ``process_formdata`` will be called after ``process_data`` for each field. If no form data is available for the given field, it is called with an empty list. - ``wtforms.ext.django`` has been overhauled, both to mirror features and changes of the Django 1.0 release, and to add some useful fields for working with django ORM data in forms. - The ``checker`` keyword argument to ``SelectField``, ``SelectMultipleField``, and ``RadioField`` has been renamed to ``coerce`` to reflect the actual functionality of this callable. Version 0.2 ----------- Released January 13th, 2009. - We have documentation and unit tests! - Fields now have a ``flags`` property which contain boolean flags that are set either by the field itself or validators being specified on a field. The flags can then be used in checks in template or python code. - Changed the way fields take parameters, they are no longer quasi magic. This is a breaking change. Please see the documentation for the new syntax. - Added optional description argument to Field, accessible on the field as ``description``. This provides an easy way to define e.g. help text in the same place as the form. - Added new semantics for validators which can stop the validation chain, with or without errors. - Added a regexp validator, and removed the not_empty validator in favour of two validators, optional and required. The new validators allow control over the validation chain in addition to checking emptiness. - Renamed ``wtforms.contrib`` to ``wtforms.ext`` and reorganised ``wtforms.ext.django``. This is a breaking change if you were using the django extensions, but should only require changing your imports around a little. - Better support for other frameworks such as Pylons. Version 0.1 ----------- Released July 25th, 2008. - Initial release. wtforms-2.2.1/LICENSE.rst000066400000000000000000000030661330632674500150470ustar00rootroot00000000000000Copyright © 2008 by the WTForms team. All rights reserved. Redistribution and use in source and binary forms of the software as well as documentation, 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. - Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE AND DOCUMENTATION 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 HOLDER 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 AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. wtforms-2.2.1/MANIFEST.in000066400000000000000000000002451330632674500147650ustar00rootroot00000000000000include AUTHORS.rst include CHANGES.rst include LICENSE.rst include README.rst graft docs prune docs/_build graft tests graft wtforms/locale global-exclude *.py[co] wtforms-2.2.1/README.rst000066400000000000000000000045071330632674500147230ustar00rootroot00000000000000WTForms ======= WTForms is a flexible forms validation and rendering library for Python web development. It is `framework agnostic`_ and can work with whatever web framework and template engine you choose. There are various community libraries that provide closer integration with popular frameworks. To get started using WTForms, we recommend reading the `crash course`_ in the docs. .. _crash course: https://wtforms.readthedocs.io/en/stable/crash_course.html .. _framework agnostic: https://wtforms.readthedocs.io/en/stable/faq.html#does-wtforms-work-with-library-here Installation ------------ Install and update using pip:: pip install -U WTForms Third-Party Library Integrations -------------------------------- WTForms is designed to work with any web framework and template engine. There are a number of community-provided libraries that make integrating with frameworks even better. - `Flask-WTF`_ integrates with the Flask framework. It can automatically load data from the request, uses Flask-Babel to translate based on user-selected locale, provides full-application CSRF, and more. - `WTForms-Alchemy`_ provides rich support for generating forms from SQLAlchemy models, including an expanded set of fields and validators. - `WTForms-SQLAlchemy`_ provides ORM-backed fields and form generation from SQLAlchemy models. - `WTForms-AppEngine`_ provides ORM-backed fields and form generation from AppEnding db/ndb schema - `WTForms-AppEngine`_ provides ORM-backed fields and form generation from Django models, as well as integration with Django's I18N support. .. _Flask-WTF: https://flask-wtf.readthedocs.io/ .. _WTForms-Alchemy: https://wtforms-alchemy.readthedocs.io/ .. _WTForms-SQLAlchemy: https://github.com/wtforms/wtforms-sqlalchemy .. _WTForms-AppEngine: https://github.com/wtforms/wtforms-appengine .. _WTForms-Django: https://github.com/wtforms/wtforms-django Links ----- - Documentation: https://wtforms.readthedocs.io/ - License: `BSD `_ - Releases: https://pypi.org/project/WTForms/ - Code: https://github.com/wtforms/wtforms - Issue tracker: https://github.com/wtforms/wtforms/issues - Test status: - Linux: https://travis-ci.org/wtforms/wtforms - Test coverage: https://coveralls.io/github/wtforms/wtforms wtforms-2.2.1/docs/000077500000000000000000000000001330632674500141565ustar00rootroot00000000000000wtforms-2.2.1/docs/Makefile000066400000000000000000000044461330632674500156260ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html web pickle htmlhelp latex changes linkcheck help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " pickle to make pickle files (usable by e.g. sphinx-web)" @echo " htmlhelp to make HTML files and a HTML help project" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " changes to make an overview over all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" clean: -rm -rf _build/* html: mkdir -p _build/html _build/doctrees $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html @echo @echo "Build finished. The HTML pages are in _build/html." pickle: mkdir -p _build/pickle _build/doctrees $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle @echo @echo "Build finished; now you can process the pickle files or run" @echo " sphinx-web _build/pickle" @echo "to start the sphinx-web server." web: pickle htmlhelp: mkdir -p _build/htmlhelp _build/doctrees $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in _build/htmlhelp." latex: mkdir -p _build/latex _build/doctrees $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex @echo @echo "Build finished; the LaTeX files are in _build/latex." @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ "run these through (pdf)latex." changes: mkdir -p _build/changes _build/doctrees $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes @echo @echo "The overview file is in _build/changes." linkcheck: mkdir -p _build/linkcheck _build/doctrees $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in _build/linkcheck/output.txt." wtforms-2.2.1/docs/_static/000077500000000000000000000000001330632674500156045ustar00rootroot00000000000000wtforms-2.2.1/docs/_static/docstyles.css000066400000000000000000000033111330632674500203250ustar00rootroot00000000000000/* Those silly paragraph link entities */ a.headerlink { color: #B4B4B4!important; font-size: 0.8em; padding: 0 4px 0 4px; text-decoration: none!important; visibility: hidden; } h1:hover > a.headerlink, h2:hover > a.headerlink, h3:hover > a.headerlink, h4:hover > a.headerlink, h5:hover > a.headerlink, h6:hover > a.headerlink, dt:hover > a.headerlink { visibility: visible; } a.headerlink:hover { background-color: #B4B4B4; color: #F0F0F0!important; } /* Links to classes/functions */ a.reference { font-weight: bold; } #wtforms-documentation ul li a.reference, #toc ul li a.reference { font-weight: normal; } /* definition links */ dl.function dt, dl.class dt, dl.exception dt, dl.method dt, dl.attribute dt { font-weight: normal; } dt .descname { font-weight: bold } /* Warning boxes and other boxy things */ div.admonition, div.warning, div#toc { font-size: 0.9em; margin: 1em 0 0 0; border: 1px solid #86989B; background-color: #f7f7f7; } div.admonition p, div.warning p, div#toc p { margin: 0.5em 1em 0.5em 1em; padding: 0; } div.admonition pre, div.warning pre, div#toc pre { margin: 0.4em 1em 0.4em 1em; } div.admonition p.admonition-title, div.warning p.admonition-title, div#toc h3 { margin: 0; padding: 0.1em 0 0.1em 0.5em; color: white; border-bottom: 1px solid #86989B; font-weight: bold; background-color: #AFC1C4; } div.warning { border: 1px solid #940000; } div.warning p.admonition-title { background-color: #CF0000; border-bottom-color: #940000; } div.admonition ul, div.admonition ol, div.warning ul, div.warning ol, div#toc ul, div#toc ol { margin: 0.1em 0.5em 0.5em 3em; padding: 0; } wtforms-2.2.1/docs/_static/main.css000066400000000000000000000020451330632674500172430ustar00rootroot00000000000000body { font: 12px/1.4em 'Verdana', sans-serif; } h1, h2, h3, h4, h5, h6 { font-family: 'Trebuchet MS'; } h1, h2, h3 { font-weight: normal; } h2 { font-size: 1.8em; } h3 { font-size: 1.4em; } h4 { font-size: 1.2em; } a { color: #880000; text-decoration: none; } a:hover { text-decoration: underline; } img { border: 0; } pre { margin-left: 20px; border-left: 1px solid #dddddd; padding: 0 10px 5px 10px; } ul { padding-left: 25px; } ul ul { padding-left: 20px; } #body { margin: auto; max-width: 850px; } #header { border-bottom: 1px solid #efefef; position: relative; } #footer { border-top: 1px solid #efefef; text-align: center; color: #888; font-size: 10px; } #logo { margin: 0; padding: 0; } #menu { position: absolute; bottom: 5px; right: 5px; margin: 0; } #menu li { display: block; float: left; list-style-type: none; padding: 0 10px; } #menu li a { display: block; } #content { padding: 0 20px 5px 20px; } wtforms-2.2.1/docs/_static/wtforms.png000066400000000000000000000124141330632674500200150ustar00rootroot00000000000000PNG  IHDRE ePLTE⡞zzzmmm|||䩤ޙ֡||ڝ|uueeeܬuuuiiiTTU˒pppƁʍHHHaaaҎXXXƈrrrȐڌ^^^֔Λй戇xxvoo~~~wyegk뙟qszZZ]甘_ad|kmrPPPxxx𻹷ᣣsssՏッ󝘘\]\ӘNNN?OIDATx}XG~Dž@!FFFĻ1ؑ!g &R\n4O."!Ʋ{ߝwrNouA "}P:LI1W̽1gs >plۂ|426ä}B+gX#?{C܁ 8_M"S(m&PX9Wcnl7n80{U)-kJK`@<:z33R `_pMSӃ,YZA%kcbx@*Ƙ <Gn ZPyy5_cp!oC砺ѝ]_?J8Cޭ|pڨPh x@ &+z$2AsAr6srزt z/(} YFj݃KCr5"Jل#;fYB !ߧBz1o>\|lRpoO9`C˙caeU9@]Ӫpz-xkpRf7 Ls-k9`󖰰L=FcSCv0PU=twiMZ.^\4<όk:97t+Y=x֧=S߰8y5%eRܼ MYb%~^.3[㠲ɼ;7(YQfj/ W_?NzP:64=u۵ܐ5%j/a&g#0ޙPo.m'ӈJgs:ŒK8/{š瘱z̻PV%/7Яct]ф%ctOIMD0\R~mAiS͗Pff-ؠN4OAG3R6AYf&n]77+aPVojϬ ˯xh"T9̌)pᑇit&5%fx<rei,IB<RTe<3i䂉2ӥ'q!2-i>Mz3ږUGEɇW?72AIM`,y7+B,1\amʘ=[W5XٖFK}1N,٠y`?j2" l |my;Mz/;v6[SSe(1}㓪2SdBd;)]gFNe{]1_ffkF1ػ l;oצ Ӥ7k]*gN kW:MR˔iRk&􉼜wN#Bu)ٱ ՓS)VIbY.l*%}qxR;% ق:8xP#b//.V ;wQ[1'7`)Z=Zwd/jl<9˒74EmK`"ҖmXfϕ\*%5Sclۆm9'Ve(9Cً>ylq9$isuꪈH[ aXU>ny$YB^@sDf2f'2gBJ< ,VU!$^bIf_$m=+$i2/厬5Je6GVh%Z]x>oT)8pyˮNJN0/Hl CIJd4YzoYU%K鋈MKm:xsAA4ӏHeRGu0赚87Qf.ƺe^C+dNbW%p-8aWkkQ%ɷɓ/?O?"TQ)xfL5˫2YAiq˭܊ :kkW\PmCɲM!Oyzˏ,,p(Sq\Sp6#lhquz`[CJB{}N.ݘVH9 9($P;!=Em7xi[z h8?[y>Zl?`BqJ 0a']( `spN|:E&.m#YGqzWêqa;zewAB] -, çz^/m;PPq] vmӝ<ƍ`hd"c*2.LOtp)Adה 9 q$ㇹPpOӝK2 cdf&[2;(,q ruF-[̷o1_#=z05%IENDB`wtforms-2.2.1/docs/_templates/000077500000000000000000000000001330632674500163135ustar00rootroot00000000000000wtforms-2.2.1/docs/_templates/layout.html000066400000000000000000000065321330632674500205240ustar00rootroot00000000000000 WTForms Documentation {%- if builder != 'htmlhelp' %} {%- endif %} {%- if use_opensearch and builder != 'htmlhelp' %} {%- endif %} {%- if hasdoc('about') %} {%- endif %} {%- if hasdoc('copyright') %} {%- endif %} {%- if parents %} {%- endif %} {%- if next %} {%- endif %} {%- if prev %} {%- endif %} {% block extrahead %}{% endblock %}
{%- if display_toc %}

Table Of Contents

{{ toc }}
{%- endif %} {% block body %}{% endblock %}
wtforms-2.2.1/docs/changes.rst000066400000000000000000000000351330632674500163160ustar00rootroot00000000000000 .. include:: ../CHANGES.rst wtforms-2.2.1/docs/conf.py000066400000000000000000000135211330632674500154570ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # WTForms documentation build configuration file, created by # sphinx-quickstart on Fri Aug 01 15:29:36 2008. # # This file is execfile()d with the current directory set to its containing dir. # # The contents of this file are pickled, so don't put values in the namespace # that aren't pickleable (module imports are okay, they're removed automatically). # # All configuration values have a default value; values that are commented out # serve to show the default value. def _fix_import_path(): """ Don't want to pollute the config globals, so do path munging here in this function """ import sys, os try: import wtforms except ImportError: parent_dir = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..')) build_lib = os.path.join(parent_dir, 'build', 'lib') if os.path.isdir(build_lib): sys.path.insert(0, build_lib) else: sys.path.insert(0, parent_dir) _fix_import_path() # General configuration # --------------------- # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The master toctree document. master_doc = 'index' # General substitutions. project = 'WTForms' copyright = '2008 by the WTForms team' # The default replacements for |version| and |release|, also used in various # other places throughout the built documents. # # The short X.Y version. version = '2.2' # The full version, including alpha/beta/rc tags. release = '2.2.1' # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. today_fmt = '%B %d, %Y' # List of documents that shouldn't be included in the build. #unused_docs = [] # List of directories, relative to source directories, that shouldn't be searched # for source files. #exclude_dirs = [] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'friendly' # Options for HTML output # ----------------------- # The style sheet to use for HTML and HTML Help pages. A file of that name # must exist either in Sphinx' static/ path, or in one of the custom paths # given in html_static_path. html_style = 'default.css' # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (within the static path) to place at the top of # the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_use_modindex = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, the reST sources are included in the HTML build as _sources/. #html_copy_source = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = '' # Output file base name for HTML help builder. htmlhelp_basename = 'WTFormsdoc' # Options for LaTeX output # ------------------------ # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, document class [howto/manual]). latex_documents = [ ('index', 'WTForms.tex', 'WTForms Documentation', 'WTForms team', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_use_modindex = True wtforms-2.2.1/docs/contributing.rst000066400000000000000000000047521330632674500174270ustar00rootroot00000000000000Contributing to WTForms ======================= WTForms is an open-source library and changing and evolving over time. To that end, we are supported by the contributions of many people in the python community. How to Contribute ----------------- WTForms is now on `GitHub`_, so all contributions should be either associated with a pull request or with a ticket & patch. .. _GitHub: https://github.com/wtforms/wtforms Contribution Guidelines ----------------------- Code submitted should: * Be formatted according to the `PEP8`_ style guideline **except** that it does not need to confirm to the 79-column limit requirement of the guideline. * Have tests - Unless it's a bugfix, it should pass existing tests. - New classes or methods should mean new unit tests or extending existing tests. - Bugfixes can probably do with a regression test too (a test that would fail without this fix) * Use naming schemes consistent with WTForms conventions * Work on all versions of Python that WTForms currently supports (and python3 without needing 2to3). Take advantage of `Travis-CI`_ for running tests on all supported Python versions. .. _Travis-CI: https://travis-ci.org .. _PEP8: https://www.python.org/dev/peps/pep-0008/ Note on API compatibility ------------------------- WTForms is a very small library, but yet it's possible to break API compatibility pretty easily. We are okay with breaking API compatibility for compelling features or major changes that we feel are worthwhile inclusions to the WTForms core, but realize that any API compatiblity break will delay the inclusion of your ticket to the next major release. Some examples of API compatibility breaks include: * Adding new attributes or methods to the base Form class * Modifying the number of required arguments of core methods like :meth:`~wtforms.fields.Field.process` * Changing the default behavior of a field. However, it is still possible to add new features to WTForms without breaking API compatibility. For example, if one were looking to add Babel locale support to DecimalField, it could be done so long as by default, DecimalField behaved the same as it did before. This could look something like: 1. Add a keyword arg ``use_locale`` to the constructor 2. Make the keyword default to ``False`` so the behavior without this arg is identical to the previous bevhavior. 3. Add your functionality and make sure all existing DecimalField tests work unchanged (and of course add new tests for the new functionality). wtforms-2.2.1/docs/crash_course.rst000066400000000000000000000343341330632674500173770ustar00rootroot00000000000000.. _crash-course: Crash Course ============ So you’ve cracked your knuckles and started working on that awesome python webapp you want to write. You get through writing a few pages and finally you need to tackle that loathsome task: form input handling and validation. Enter WTForms. But why do I need *yet another* framework? Well, some webapp frameworks take the approach of associating database models with form handling. While this can be handy for very basic create/update views, chances are not every form you need can map directly to a database model. Or maybe you already use a generic form handling framework but you want to customize the HTML generation of those form fields, and define your own validation. With WTForms, your form field HTML can be generated for you, but we let you customize it in your templates. This allows you to maintain separation of code and presentation, and keep those messy parameters out of your python code. Because we strive for loose coupling, you should be able to do that in any templating engine you like, as well. .. _download-installation: Download / Installation ----------------------- WTForms is available through `PyPI`_. Install it using pip:: pip install WTForms .. _PyPI: https://pypi.org/project/WTForms/ Key Concepts ------------ - :class:`Forms ` are the core container of WTForms. Forms represent a collection of fields, which can be accessed on the form dictionary-style or attribute style. - :mod:`Fields ` do most of the heavy lifting. Each field represents a *data type* and the field handles coercing form input to that datatype. For example, `IntegerField` and `StringField` represent two different data types. Fields contain a number of useful properties, such as a label, description, and a list of validation errors, in addition to the data the field contains. - Every field has a :mod:`Widget ` instance. The widget's job is rendering an HTML representation of that field. Widget instances can be specified for each field but every field has one by default which makes sense. Some fields are simply conveniences, for example :class:`~wtforms.fields.TextAreaField` is simply a :class:`~wtforms.fields.StringField` with the default widget being a :class:`~wtforms.widgets.TextArea`. - In order to specify validation rules, fields contain a list of :mod:`Validators `. Getting Started --------------- Let's get right down to business and define our first form:: from 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()]) When you create a form, you define the fields in a way that is similar to the way many ORM’s have you define their columns: By defining class variables which are instantiations of the fields. Because forms are regular Python classes, you can easily extend them as you would expect:: class 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)]) Via subclassing, `AdminProfileForm` gains all the fields already defined in `ProfileForm`. This allows you to easily share common subsets of fields between forms, such as the example above, where we are adding admin-only fields to `ProfileForm`. Using Forms ~~~~~~~~~~~ Using a form is as simple as instantiating it. Consider the following django-like view, using the `RegistrationForm` we defined earlier:: def 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) First, we instantiate the form, providing it with any data available in ``request.POST``. We then check if the request is made using POST, and if it is, we validate the form, and check that the user accepted the rules. If successful, we create a new User and assign the data from the validated form to it, and save it. Editing existing objects ^^^^^^^^^^^^^^^^^^^^^^^^ Our earlier registration example showed how to accept input and validate it for new entries, but what if we want to edit an existing object? Easy:: def 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) Here, we instantiate the form by providing both request.POST and the user object to the form. By doing this, the form will get any data that isn't present in the post data from the `user` object. We're also using the form's `populate_obj` method to re-populate the user object with the contents of the validated form. This method is provided for convenience, for use when the field names match the names on the object you're providing with data. Typically, you will want to assign the values manually, but for this simple case it's perfect. It can also be useful for CRUD and admin forms. Exploring in the console ^^^^^^^^^^^^^^^^^^^^^^^^ WTForms forms are very simple container objects, and perhaps the easiest way to find out what's available to you in a form is to play around with a form in the console:: >>> 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.']} What we've found here is that when you instantiate a form, it contains instances of all the fields, which can be accessed via either dictionary-style or attribute-style. These fields have their own properties, as does the enclosing form. When we validate the form, it returns False, meaning at least one validator was not satisfied. :attr:`form.errors ` will give you a summary of all the errors. .. code-block:: python >>> form2 = UsernameForm(username=u'Robert') >>> form2.data {'username': u'Robert'} >>> form2.validate() True This time, we passed a new value for username when instantiating UserForm, and it was sufficient to validate the form. How Forms get data ~~~~~~~~~~~~~~~~~~ In addition to providing data using the first two arguments (`formdata` and `obj`), you can pass keyword arguments to populate the form. Note though that a few names are reserved: `formdata`, `obj`, and `prefix`. `formdata` takes precendence over `obj`, which itself takes precedence over keyword arguments. For example:: def 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) While you almost never use all three methods together in practice, it illustrates how WTForms looks up the `username` field: 1. If a form was submitted (request.POST is not empty), process the form input. Even if there was no form input for this field in particular, if there exists form input of any sort, then we will process the form input. 2. If there was no form input, then try the following in order: 1. Check if `user` has an attribute named `username`. 2. Check if a keyword argument named `username` was provided. 3. Finally, if everything else fails, use the default value provided by the field, if any. Validators ~~~~~~~~~~ Validation in WTForms is done by providing a field with a set of validators to run when the containing form is validated. You provide these via the field constructor's second argument, `validators`:: class ChangeEmailForm(Form): email = StringField('Email', [validators.Length(min=6, max=120), validators.Email()]) You can provide any number of validators to a field. Typically, you will want to provide a custom error message:: class 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.')) ]) It is generally preferable to provide your own messages, as the default messages by necessity are generic. This is also the way to provide localised error messages. For a list of all the built-in validators, check the :mod:`Validators Reference ` Rendering Fields ~~~~~~~~~~~~~~~~ Rendering a field is as simple as coercing it to a string:: >>> from wtforms import Form, StringField >>> class SimpleForm(Form): ... content = StringField('content') ... >>> form = SimpleForm(content='foobar') >>> str(form.content) '' >>> unicode(form.content) u'' However, the real power comes from rendering the field with its :meth:`~wtforms.fields.Field.__call__` method. By calling the field, you can provide keyword arguments, which will be injected as html attributes in the output:: >>> form.content(style="width: 200px;", class_="bar") u'' Now let's apply this power to rendering a form in a `Jinja `_ template. First, our form:: class LoginForm(Form): username = StringField('Username') password = PasswordField('Password') form = LoginForm() And the template: .. code-block:: html+jinja
{{ form.username.label }}: {{ form.username(class="css_class") }}
{{ form.password.label }}: {{ form.password() }}
Alternately, if you're using Django templates, you can use the `form_field` templatetag we provide in our Django extension, when you want to pass keyword arguments: .. code-block:: html+django {% load wtforms %}
{{ form.username.label }}: {% form_field form.username class="css_class" %}
{{ form.password.label }}: {{ form.password }}
Both of these will output: .. code-block:: html
:
:
WTForms is template engine agnostic, and will work with anything that allows attribute access, string coercion, and/or function calls. The `form_field` templatetag is provided as a convenience as you can't pass arguments in Django templates. Displaying Errors ~~~~~~~~~~~~~~~~~ Now that we have a template for our form, let's add error messages: .. code-block:: html+jinja
{{ form.username.label }}: {{ form.username(class="css_class") }}
{% if form.username.errors %}
    {% for error in form.username.errors %}
  • {{ error }}
  • {% endfor %}
{% endif %}
{{ form.password.label }}: {{ form.password() }}
{% if form.password.errors %}
    {% for error in form.password.errors %}
  • {{ error }}
  • {% endfor %}
{% endif %}
If you prefer one big list of errors at the top, this is also easy: .. code-block:: html+jinja {% if form.errors %}
    {% for field_name, field_errors in form.errors|dictsort if field_errors %} {% for error in field_errors %}
  • {{ form[field_name].label }}: {{ error }}
  • {% endfor %} {% endfor %}
{% endif %} As error handling can become a rather verbose affair, it is preferable to use Jinja macros (or equivalent) to reduce boilerplate in your templates. (:ref:`example `) Custom Validators ~~~~~~~~~~~~~~~~~ There are two ways to provide custom validators. By defining a custom validator and using it on a field:: from 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]) Or by providing an in-form field-specific validator:: class FourtyTwoForm(Form): num = IntegerField('Number') def validate_num(form, field): if field.data != 42: raise ValidationError(u'Must be 42') For more complex validators that take parameters, check the :ref:`custom-validators` section. Next Steps ---------- The crash course has just skimmed the surface on how you can begin using WTForms to handle form input and validation in your application. For more information, you'll want to check the following: - The :ref:`WTForms documentation ` has API documentation for the entire library. - :ref:`specific_problems` can help you tackle specific integration issues with WTForms and other frameworks. wtforms-2.2.1/docs/csrf.rst000066400000000000000000000253601330632674500156530ustar00rootroot00000000000000CSRF Protection =============== .. module:: wtforms.csrf The CSRF package includes tools that help you implement checking against cross-site request forgery ("csrf"). Due to the large number of variations on approaches people take to CSRF (and the fact that many make compromises) the base implementation allows you to plug in a number of CSRF validation approaches. CSRF implementations are made by subclassing :class:`~wtforms.csrf.core.CSRF`. For utility, we have provided one possible CSRF implementation in the package that can be used with many frameworks for session-based hash secure keying, :class:`~wtforms.csrf.session.SessionCSRF`. Using CSRF ---------- CSRF in WTForms 2.0 is now driven through a number of variables on :mod:`class Meta `. After choosing a CSRF implementation, import it and configure it on the class Meta of a subclass of Form like such:: from somemodule import SomeCSRF class MyBaseForm(Form): class Meta: csrf = True # Enable CSRF csrf_class = SomeCSRF # Set the CSRF implementation csrf_secret = b'foobar' # Some implementations need a secret key. # Any other CSRF settings here. And once you've got this set up, you can define your forms as a subclass of `MyBaseForm`: .. code-block:: python class UserForm(MyBaseForm): name = TextField() age = IntegerField() def view(): form = UserForm(request.POST) if request.POST and form.validate(): pass # Form is valid and CSRF succeeded return render('user.html', form=form) There is a special field inside the CSRF form (called ``csrf_token`` by default) which you need to make sure you render in your template: .. code-block:: html+jinja
{{ form.csrf_token }} {% if form.csrf_token.errors %}
You have submitted an invalid CSRF token
{% endif %}
{{ form.name }} {{ form.name.label }}
{{ form.age }}{{ form.age.label }}
Remember, with the `class Meta` you can always override variables in a sub-class or at the constructor for special-cases:: class SearchForm(MyBaseForm): """ We expect search queries to come externally, thus we don't want CSRF even though it's set up on the base form. """ class Meta: # This overrides the value from the base form. csrf = False How WTForms CSRF works ---------------------- Most CSRF implementations hinge around creating a special token, which is put in a hidden field on the form named `csrf_token`, which must be rendered in your template to be passed from the browser back to your view. There are many different methods of generating this token, but they are usually the result of a cryptographic hash function against some data which would be hard to forge. .. module:: wtforms.csrf.core .. autoclass:: CSRFTokenField .. automethod:: __init__ .. autoattribute:: current_token .. automethod:: _value .. automethod:: populate_obj .. automethod:: pre_validate .. automethod:: process .. autoclass:: CSRF .. automethod:: setup_form .. automethod:: generate_csrf_token .. automethod:: validate_csrf_token .. autoattribute:: field_class The class of the token field we're going to construct. Can be overridden in subclasses if need be. Creating your own CSRF implementation ------------------------------------- Here we will sketch out a simple theoretical CSRF implementation which generates a hash token based on the user's IP. **Note** This is a simplistic example meant to illustrate creating a CSRF implementation. This isn't recommended to be used in production because the token is deterministic and non-changing per-IP, which means this isn't the most secure implementation of CSRF. First, let's create our CSRF class:: from wtforms.csrf.core import CSRF from hashlib import md5 SECRET_KEY = '1234567890' class IPAddressCSRF(CSRF): """ Generate a CSRF token based on the user's IP. I am probably not very secure, so don't use me. """ def setup_form(self, form): self.csrf_context = form.meta.csrf_context return super(IPAddressCSRF, self).setup_form(form) def generate_csrf_token(self, csrf_token): token = md5(SECRET_KEY + self.csrf_context).hexdigest() return token def validate_csrf_token(self, form, field): if field.data != field.current_token: raise ValueError('Invalid CSRF') Now that we have this taken care of, let's write a simple form and view which would implement this:: class RegistrationForm(Form): class Meta: csrf = True csrf_class = IPAddressCSRF name = StringField('Your Name') email = StringField('Email', [validators.email()]) def register(request): form = RegistrationForm( request.POST, meta={'csrf_context': request.ip} ) if request.method == 'POST' and form.validate(): pass # We're all good, create a user or whatever it is you do elif form.csrf_token.errors: pass # If we're here we suspect the user of cross-site request forgery else: pass # Any other errors return render('register.html', form=form) And finally, a simple template: .. code-block:: html+jinja {{ form.csrf_token }}

{{ form.name.label }}: {{ form.name }}

{{ form.email.label }}: {{ form.email }}

Please note that implementing CSRF detection is not fool-proof, and even with the best CSRF protection implementation, it's possible for requests to be forged by expert attackers. However, a good CSRF protection would make it infeasible for someone from an external site to hijack a form submission from another user and perform actions as them without additional a priori knowledge. In addition, it's important to understand that very often, the more strict the CSRF protection, the higher the chance of false positives occurring (ie, legitimate users getting blocked by your CSRF protection) and choosing a CSRF implementation is actually a matter of compromise. We will attempt to provide a handful of usable reference algorithms built in to this library in the future, to allow that choice to be easy. Some tips on criteria people often examine when evaluating CSRF implementations: * **Reproducability** If a token is based on attributes about the user, it gains the advantage that one does not need secondary storage in which to store the value between requests. However, if the same attributes can be reproduced by an attacker, then the attacker can potentially forge this information. * **Reusability**. It might be desired to make a completely different token every use, and disallow users from re-using past tokens. This is an extremely powerful protection, but can have consequences on if the user uses the back button (or in some cases runs forms simultaneously in multiple browser tabs) and submits an old token, or otherwise. A possible compromise is to allow reusability in a time window (more on that later). * **Time Ranges** Many CSRF approaches use time-based expiry to make sure that a token cannot be (re)used beyond a certain point. Care must be taken in choosing the time criteria for this to not lock out legitimate users. For example, if a user might walk away while filling out a long-ish form, or to go look for their credit card, the time for expiry should take that into consideration to provide a balance between security and limiting user inconvenience. * **Requirements** Some CSRF-prevention methods require the use of browser cookies, and some even require client-side scripting support. The webmaster implementing the CSRF needs to consider that such requirements (though effective) may lock certain legitimate users out, and make this determination whether it is a good idea to use. For example, for a site already using cookies for login, adding another for CSRF isn't as big of a deal, but for other sites it may not be feasible. Session-based CSRF implementation --------------------------------- .. automodule:: wtforms.csrf.session .. autoclass:: SessionCSRF **Meta Values** * ``csrf_secret`` A byte string which is the master key by which we encode all values. Set to a sufficiently long string of characters that is difficult to guess or bruteforce (recommended at least 16 characters) for example the output of ``os.urandom(16)``. * ``csrf_time_limit`` if `None`, tokens last forever (not recommended.) Otherwise, set to a ``datetime.timedelta`` that will define how long CSRF tokens are valid for. Defaults to 30 minutes. * ``csrf_context`` This should be a ``request.session``-style object. Usually given in the Form constructor. Example ~~~~~~~ .. code-block:: python from wtforms.csrf.session import SessionCSRF from datetime import timedelta class MyBaseForm(Form): class Meta: csrf = True csrf_class = SessionCSRF csrf_secret = b'EPj00jpfj8Gx1SjnyLxwBBSQfnQ9DJYe0Ym' csrf_time_limit = timedelta(minutes=20) class Registration(MyBaseForm): name = StringField() def view(request): form = Registration(request.POST, meta={'csrf_context': request.session}) # rest of view here Note that request.session is passed as the ``csrf_context`` override to the meta info, this is so that the CSRF token can be stored in your session for comparison on a later request. Example Integration ~~~~~~~~~~~~~~~~~~~ WTForms primitives are designed to work with a large variety of frameworks, and as such sometimes things seem like they are more work to use, but with some smart integration, you can actually clean up your code substantially. For example, if you were going to integrate with `Flask`_, and wanted to use the SessionCSRF implementation, here's one way to get the CSRF context to be available without passing it all the time: .. code-block:: python from flask import session from wtforms.csrf.session import SessionCSRF class MyBaseForm(Form): class Meta: csrf = True csrf_class = SessionCSRF csrf_secret = app.config['CSRF_SECRET_KEY'] @property def csrf_context(self): return session Now with any subclasses of MyBaseForm, you don't need to pass in the csrf context, and on top of that, we grab the secret key out of your normal app configuration. .. _Flask: http://flask.pocoo.org/ wtforms-2.2.1/docs/ext.rst000066400000000000000000000244061330632674500155160ustar00rootroot00000000000000Extensions ========== .. module:: wtforms.ext WTForms ships with a number of extensions that make it easier to work with other frameworks and libraries, such as Django. Appengine --------- .. module:: wtforms.ext.appengine WTForms includes support for AppEngine fields as well as auto-form generation from models. .. deprecated:: 2.0 ``wtforms.ext.appengine`` is now deprecated, and will be removed in WTForms 3.0. For an appengine module that will continue to be updated, see `WTForms-Appengine`_ .. _WTForms-Appengine: https://github.com/wtforms/wtforms-appengine Model Forms ~~~~~~~~~~~ .. module:: wtforms.ext.appengine.db See the module docstring for examples on how to use :func:`model_form`. .. autofunction:: model_form(model, base_class=Form, only=None, exclude=None, field_args=None, converter=None) Datastore-backed Fields ~~~~~~~~~~~~~~~~~~~~~~~ .. module:: wtforms.ext.appengine.fields .. autoclass:: ReferencePropertyField(default field arguments, reference_class=None, get_label=None, allow_blank=False, blank_text='') .. autoclass:: StringListPropertyField(default field arguments) .. autoclass:: GeoPtPropertyField(default field arguments) NDB ~~~ WTForms includes support for NDB models and can support mapping the relationship fields as well as generating forms from models. .. autoclass:: KeyPropertyField(default field arguments, reference_class=None, get_label=None, allow_blank=False, blank_text='') .. module:: wtforms.ext.appengine.ndb .. autofunction:: model_form(model, base_class=Form, only=None, exclude=None, field_args=None, converter=None) Dateutil -------- .. module:: wtforms.ext.dateutil .. module:: wtforms.ext.dateutil.fields For better date-time parsing using the `python-dateutil`_ package, :mod:`wtforms.ext.dateutil` provides a set of fields to use to accept a wider range of date input. .. _python-dateutil: https://dateutil.readthedocs.io/ .. autoclass:: DateTimeField(default field arguments, parse_kwargs=None, display_format='%Y-%m-%d %H:%M') .. autoclass:: DateField(default field arguments, parse_kwargs=None, display_format='%Y-%m-%d') Django ------ .. module:: wtforms.ext.django This extension provides templatetags to make it easier to work with Django templates and WTForms' html attribute rendering. It also provides a generator for automatically creating forms based on Django ORM models. .. deprecated:: 2.0 ``wtforms.ext.django`` is now deprecated, and will be removed in WTForms 3.0. For Django support that will continue to be updated, see `WTForms-Django`_ .. _WTForms-Django: https://github.com/wtforms/wtforms-django Templatetags ~~~~~~~~~~~~ .. module:: wtforms.ext.django.templatetags.wtforms Django templates do not allow arbitrarily calling functions with parameters, making it impossible to use the html attribute rendering feature of WTForms. To alleviate this, we provide a templatetag. Adding :mod:`wtforms.ext.django` to your INSTALLED_APPS will make the wtforms template library available to your application. With this you can pass extra attributes to form fields similar to the usage in jinja: .. code-block:: django {% load wtforms %} {% form_field form.username class="big_text" onclick="do_something()" %} **Note** By default, using the `{{ form.field }}` syntax in django models will be auto-escaped. To avoid this happening, use Django's `{% autoescape off %}` block tag or use WTForms' `form_field` template tag. Model forms ~~~~~~~~~~~ .. module:: wtforms.ext.django.orm .. autofunction:: model_form(model, base_class=Form, only=None, exclude=None, field_args=None, converter=None) :func:`model_form` attempts to glean as much metadata as possible from inspecting the model's fields, and will even attempt to guess at what validation might be wanted based on the field type. For example, converting an `EmailField` will result in a :class:`~wtforms.fields.StringField` with the :class:`~wtforms.validators.Email` validator on it. if the `blank` property is set on a model field, the resulting form field will have the :class:`~wtforms.validators.Optional` validator set. Just like any other Form, forms created by model_form can be extended via inheritance:: UserFormBase = model_form(User) class UserForm(UserFormBase): new_pass = PasswordField('', [validators.optional(), validators.equal_to('confirm_pass')]) confirm_pass = PasswordField() When combined with :meth:`form iteration `, model_form is a handy way to generate dynamic CRUD forms which update with added fields to the model. One must be careful though, as it's possible the generated form fields won't be as strict with validation as a hand-written form might be. ORM-backed fields ~~~~~~~~~~~~~~~~~ .. module:: wtforms.ext.django.fields While linking data to most fields is fairly easy, making drop-down select lists using django ORM data can be quite repetitive. To this end, we have added some helpful tools to use the django ORM along with wtforms. .. autoclass:: QuerySetSelectField(default field args, queryset=None, get_label=None, allow_blank=False, blank_text=u'') .. code-block:: python class ArticleEdit(Form): title = StringField() column = QuerySetSelectField(get_label='title', allow_blank=True) category = QuerySetSelectField(queryset=Category.objects.all()) def edit_article(request, id): article = Article.objects.get(pk=id) form = ArticleEdit(obj=article) form.column.queryset = Column.objects.filter(author=request.user) As shown in the above example, the queryset can be set dynamically in the view if needed instead of at form construction time, allowing the select field to consist of choices only relevant to the user. .. autoclass:: ModelSelectField(default field args, model=None, get_label='', allow_blank=False, blank_text=u'') SQLAlchemy ---------- .. module:: wtforms.ext.sqlalchemy This extension provides SelectField integration with SQLAlchemy ORM models, similar to those in the Django extension. ORM-backed fields ~~~~~~~~~~~~~~~~~ .. module:: wtforms.ext.sqlalchemy.fields These fields are provided to make it easier to use data from ORM objects in your forms. .. code-block:: python def enabled_categories(): return Category.query.filter_by(enabled=True) class BlogPostEdit(Form): title = StringField() blog = QuerySelectField(get_label='title') category = QuerySelectField(query_factory=enabled_categories, allow_blank=True) def edit_blog_post(request, id): post = Post.query.get(id) form = BlogPostEdit(obj=post) # Since we didn't provide a query_factory for the 'blog' field, we need # to set a dynamic one in the view. form.blog.query = Blog.query.filter(Blog.author == request.user).order_by(Blog.name) .. autoclass:: QuerySelectField(default field args, query_factory=None, get_pk=None, get_label=None, allow_blank=False, blank_text=u'') .. autoclass:: QuerySelectMultipleField(default field args, query_factory=None, get_pk=None, get_label=None) Model forms ~~~~~~~~~~~ .. module:: wtforms.ext.sqlalchemy.orm It is possible to generate forms from SQLAlchemy models similarly to how it can be done for Django ORM models. .. autofunction:: model_form CSRF ---- .. module:: wtforms.ext.csrf .. deprecated:: 2.0 wtforms.ext.csrf is deprecated, as CSRF is now provided as a part of the core of WTForms. This module exists as-is for backwards compatibility and will be removed in WTForms 3.0. See the :doc:`CSRF Docs `. The CSRF package includes tools that help you implement checking against cross-site request forgery ("csrf"). Due to the large number of variations on approaches people take to CSRF (and the fact that many make compromises) the base implementation allows you to plug in a number of CSRF validation approaches. CSRF implementations are made by subclassing :class:`~wtforms.ext.csrf.form.SecureForm`. For utility, we have provided one possible CSRF implementation in the package that can be used with many frameworks for session-based hash secure keying, :class:`~wtforms.ext.csrf.session.SessionSecureForm`. All CSRF implementations hinge around creating a special token, which is put in a hidden field on the form named 'csrf_token', which must be rendered in your template to be passed from the browser back to your view. There are many different methods of generating this token, but they are usually the result of a cryptographic hash function against some data which would be hard to forge. .. module:: wtforms.ext.csrf.form .. autoclass:: SecureForm .. automethod:: generate_csrf_token .. automethod:: validate_csrf_token Session-based CSRF implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. automodule:: wtforms.ext.csrf.session **Usage** First, create a SessionSecureForm subclass that you can use as your base class for any forms you want CSRF support for:: from wtforms.ext.csrf.session import SessionSecureForm class MyBaseForm(SessionSecureForm): SECRET_KEY = 'EPj00jpfj8Gx1SjnyLxwBBSQfnQ9DJYe0Ym' TIME_LIMIT = timedelta(minutes=20) Now incorporate it into any form/view by further subclassing:: class Registration(MyBaseForm): name = StringField() def view(request): form = Registration(request.POST, csrf_context=request.session) # rest of view here Note that request.session is passed as the ``csrf_context=`` parameter, this is so that the CSRF token can be stored in your session for comparison on a later request. .. autoclass:: SessionSecureForm A provided CSRF implementation which puts CSRF data in a session. Must be subclassed to be used. **Class Attributes** .. attribute:: SECRET_KEY Must be set by subclasses to a random byte string that will be used to generate HMAC digests. .. attribute:: TIME_LIMIT If None, CSRF tokens never expire. If set to a ``datetime.timedelta``, this is how long til a generated token expires. Defaults to ``timedelta(minutes=30)`` I18n ---- .. module:: wtforms.ext.i18n .. deprecated:: 2.0 I18n extension is now deprecated in favor of using the built-in locales support on the form. .. module:: wtforms.ext.i18n.form .. autoclass:: Form wtforms-2.2.1/docs/faq.rst000066400000000000000000000105141330632674500154600ustar00rootroot00000000000000FAQ === This contains the most commonly asked questions about WTForms. The most current version of this document can always be found on the `WTForms Website`_. .. _WTForms Website: https://wtforms.readthedocs.io/ Does WTForms work with [library here]? -------------------------------------- The answer is most likely **yes**. WTForms tries to provide as usable an API as possible. We've listed here some of the known libraries to work with WTForms, but if it's not listed, it doesn't mean it won't work. * **Request/Form Input** * Django * Webob (Includes Pylons, Google App Engine, Turbogears) * Werkzeug (Includes Flask, Tipfy) * any other cgi.FieldStorage-type multidict * **Templating Engines** * Jinja2 * Mako * Django Templates (To get the full power of WTForms in your templates, you will need to use the Django :mod:`extension `.) * Genshi * **Database Objects** * Pretty much any ORM or object-DB should work, as long as data objects allow attribute access to their members. Special support is there for SQLAlchemy, Google App Engine, and Django collections via :mod:`extensions `. Does WTForms support unicode? ----------------------------- Simple answer: Yes. Longer answer: WTForms uses unicode strings throughout the source code, and assumes that form input has already been coerced to unicode by your framework (Most frameworks already do this.) WTForms fields render to unicode strings by default, and therefore as long as your templating engine can work with that, you should have no unicode issues. What versions of Python are supported? -------------------------------------- WTForms supports Python 2.6-2.7 and 3.2+ with a single codebase. Without 2to3 tool. How can I contribute to WTForms? -------------------------------- WTForms is not that scary. Really. We try to keep it as succinct and readable as possible. For bugs and feature requests, you can file a ticket on the `project page`_. .. _project page: https://github.com/wtforms/wtforms How do I mark in a template when a field is required? ----------------------------------------------------- Some validators (notably Required and Optional) set flags on the fields' :attr:`~wtforms.fields.Field.flags` object. To use this in a template, you can do something like: .. code-block:: html+jinja {% for field in form %} {{ field }} {% if field.flags.required %}*{% endif %}{{ field.label }} {% endfor %} Does WTForms handle file uploads? --------------------------------- Currently, it does not. This is because WTForms strives to be framework-agnostic, and every web framework handles file uploads somewhat differently. WTForms has a :class:`~wtforms.fields.FileField` which will let you render a file input widget, but the rest is up to you. An example use in a django-ish framework:: class MyForm(Form): image = FileField() def my_view(request): form = MyForm(request.POST) file_wrapper = request.FILES[form.image.name] # Do things with your file wrapper now Using ``form.image.name`` is an easy way to know what input name was generated for your file input, even if the form is prefixed. Why does blank input not go back to the default value? ------------------------------------------------------ A key design decision of WTForms was that form data -always- takes precedence when there's a form submission. That is, if a field exists on a form, and a form was posted, but that field's value was missing, it will not revert to a default, but instead store an empty value (and in some cases cause a validation error.) This is for a number of reasons: 1. Security. If a form reverted to defaults on missing data, then an evil user could potentially cause problems by submitting a hand-coded form with key missing fields. 2. Bug-finding. If you omitted a field in your template, it might fall through to the default and you'd possibly miss it. 3. Consistency. See the following mailing list posts for more discussion on the topic: - https://groups.google.com/forum/#!topic/wtforms/BnVaRaE4eOk - https://groups.google.com/forum/#!msg/wtforms/nF-TVnfxft4/Lfa2iYycQPoJ How do I... [convoluted combination of libraries] ------------------------------------------------- You'll probably want to check out our :ref:`Solving Specific Problems ` doc. wtforms-2.2.1/docs/fields.rst000066400000000000000000000452211330632674500161620ustar00rootroot00000000000000Fields ====== .. module:: wtforms.fields Fields are responsible for rendering and data conversion. They delegate to validators for data validation. Field definitions ----------------- Fields are defined as members on a form in a declarative fashion:: class MyForm(Form): name = StringField(u'Full Name', [validators.required(), validators.length(max=10)]) address = TextAreaField(u'Mailing Address', [validators.optional(), validators.length(max=200)]) When a field is defined on a form, the construction parameters are saved until the form is instantiated. At form instantiation time, a copy of the field is made with all the parameters specified in the definition. Each instance of the field keeps its own field data and errors list. The label and validators can be passed to the constructor as sequential arguments, while all other arguments should be passed as keyword arguments. Some fields (such as :class:`SelectField`) can also take additional field-specific keyword arguments. Consult the built-in fields reference for information on those. The Field base class -------------------- .. class:: Field Stores and processes data, and generates HTML for a form field. Field instances contain the data of that instance as well as the functionality to render it within your Form. They also contain a number of properties which can be used within your templates to render the field and label. **Construction** .. automethod:: __init__ **Validation** To validate the field, call its `validate` method, providing a form and any extra validators needed. To extend validation behaviour, override `pre_validate` or `post_validate`. .. automethod:: validate .. automethod:: pre_validate .. automethod:: post_validate .. attribute:: errors If `validate` encounters any errors, they will be inserted into this list. **Data access and processing** To handle incoming data from python, override `process_data`. Similarly, to handle incoming data from the outside, override `process_formdata`. .. automethod:: process(formdata [, data]) .. automethod:: process_data .. automethod:: process_formdata .. attribute:: data Contains the resulting (sanitized) value of calling either of the process methods. Note that it is not HTML escaped when using in templates. .. attribute:: raw_data If form data is processed, is the valuelist given from the formdata wrapper. Otherwise, `raw_data` will be `None`. .. attribute:: object_data This is the data passed from an object or from kwargs to the field, stored unmodified. This can be used by templates, widgets, validators as needed (for comparison, for example) **Rendering** To render a field, simply call it, providing any values the widget expects as keyword arguments. Usually the keyword arguments are used for extra HTML attributes. .. automethod:: __call__ If one wants to pass the "class" argument which is a reserved keyword in some python-based templating languages, one can do:: form.field(class_="text_blob") This will output (for a text field): .. code-block:: html Note: Simply coercing the field to a string or unicode will render it as if it was called with no arguments. .. automethod:: __html__ Many template engines use the __html__ method when it exists on a printed object to get an 'html-safe' string that will not be auto-escaped. To allow for printing a bare field without calling it, all WTForms fields implement this method as well. **Message Translations** .. automethod:: gettext .. automethod:: ngettext **Properties** .. attribute:: name The HTML form name of this field. This is the name as defined in your Form prefixed with the `prefix` passed to the Form constructor. .. attribute:: short_name The un-prefixed name of this field. .. attribute:: id The HTML ID of this field. If unspecified, this is generated for you to be the same as the field name. .. attribute:: label This is a :class:`Label` instance which when evaluated as a string returns an HTML ``