Merge branch 'master' of github.com:mitsuhiko/flask
This commit is contained in:
commit
04a3eeee3b
7 changed files with 38 additions and 29 deletions
2
CHANGES
2
CHANGES
|
|
@ -94,6 +94,8 @@ Version 0.10.2
|
||||||
- Changed logic of before first request handlers to flip the flag after
|
- Changed logic of before first request handlers to flip the flag after
|
||||||
invoking. This will allow some uses that are potentially dangerous but
|
invoking. This will allow some uses that are potentially dangerous but
|
||||||
should probably be permitted.
|
should probably be permitted.
|
||||||
|
- Fixed Python 3 bug when a handler from `app.url_build_error_handlers`
|
||||||
|
reraises the `BuildError`.
|
||||||
|
|
||||||
Version 0.10.1
|
Version 0.10.1
|
||||||
--------------
|
--------------
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ Gevent
|
||||||
-------
|
-------
|
||||||
|
|
||||||
`Gevent`_ is a coroutine-based Python networking library that uses
|
`Gevent`_ is a coroutine-based Python networking library that uses
|
||||||
`greenlet`_ to provide a high-level synchronous API on top of `libevent`_
|
`greenlet`_ to provide a high-level synchronous API on top of `libev`_
|
||||||
event loop::
|
event loop::
|
||||||
|
|
||||||
from gevent.wsgi import WSGIServer
|
from gevent.wsgi import WSGIServer
|
||||||
|
|
@ -42,7 +42,7 @@ event loop::
|
||||||
|
|
||||||
.. _Gevent: http://www.gevent.org/
|
.. _Gevent: http://www.gevent.org/
|
||||||
.. _greenlet: http://greenlet.readthedocs.org/en/latest/
|
.. _greenlet: http://greenlet.readthedocs.org/en/latest/
|
||||||
.. _libevent: http://libevent.org/
|
.. _libev: http://software.schmorp.de/pkg/libev.html
|
||||||
|
|
||||||
Twisted Web
|
Twisted Web
|
||||||
-----------
|
-----------
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
Form Validation with WTForms
|
Form Validation with WTForms
|
||||||
============================
|
============================
|
||||||
|
|
||||||
When you have to work with form data submitted by a browser view code
|
When you have to work with form data submitted by a browser view, code
|
||||||
quickly becomes very hard to read. There are libraries out there designed
|
quickly becomes very hard to read. There are libraries out there designed
|
||||||
to make this process easier to manage. One of them is `WTForms`_ which we
|
to make this process easier to manage. One of them is `WTForms`_ which we
|
||||||
will handle here. If you find yourself in the situation of having many
|
will handle here. If you find yourself in the situation of having many
|
||||||
|
|
@ -12,10 +12,10 @@ first. I recommend breaking up the application into multiple modules
|
||||||
(:ref:`larger-applications`) for that and adding a separate module for the
|
(:ref:`larger-applications`) for that and adding a separate module for the
|
||||||
forms.
|
forms.
|
||||||
|
|
||||||
.. admonition:: Getting most of WTForms with an Extension
|
.. admonition:: Getting the most out of WTForms with an Extension
|
||||||
|
|
||||||
The `Flask-WTF`_ extension expands on this pattern and adds a few
|
The `Flask-WTF`_ extension expands on this pattern and adds a
|
||||||
handful little helpers that make working with forms and Flask more
|
few little helpers that make working with forms and Flask more
|
||||||
fun. You can get it from `PyPI
|
fun. You can get it from `PyPI
|
||||||
<https://pypi.python.org/pypi/Flask-WTF>`_.
|
<https://pypi.python.org/pypi/Flask-WTF>`_.
|
||||||
|
|
||||||
|
|
@ -54,8 +54,8 @@ In the view function, the usage of this form looks like this::
|
||||||
return redirect(url_for('login'))
|
return redirect(url_for('login'))
|
||||||
return render_template('register.html', form=form)
|
return render_template('register.html', form=form)
|
||||||
|
|
||||||
Notice that we are implying that the view is using SQLAlchemy here
|
Notice we're implying that the view is using SQLAlchemy here
|
||||||
(:ref:`sqlalchemy-pattern`) but this is no requirement of course. Adapt
|
(:ref:`sqlalchemy-pattern`), but that's not a requirement, of course. Adapt
|
||||||
the code as necessary.
|
the code as necessary.
|
||||||
|
|
||||||
Things to remember:
|
Things to remember:
|
||||||
|
|
@ -64,14 +64,14 @@ Things to remember:
|
||||||
the data is submitted via the HTTP ``POST`` method and
|
the data is submitted via the HTTP ``POST`` method and
|
||||||
:attr:`~flask.request.args` if the data is submitted as ``GET``.
|
:attr:`~flask.request.args` if the data is submitted as ``GET``.
|
||||||
2. to validate the data, call the :func:`~wtforms.form.Form.validate`
|
2. to validate the data, call the :func:`~wtforms.form.Form.validate`
|
||||||
method which will return ``True`` if the data validates, ``False``
|
method, which will return ``True`` if the data validates, ``False``
|
||||||
otherwise.
|
otherwise.
|
||||||
3. to access individual values from the form, access `form.<NAME>.data`.
|
3. to access individual values from the form, access `form.<NAME>.data`.
|
||||||
|
|
||||||
Forms in Templates
|
Forms in Templates
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
Now to the template side. When you pass the form to the templates you can
|
Now to the template side. When you pass the form to the templates, you can
|
||||||
easily render them there. Look at the following example template to see
|
easily render them there. Look at the following example template to see
|
||||||
how easy this is. WTForms does half the form generation for us already.
|
how easy this is. WTForms does half the form generation for us already.
|
||||||
To make it even nicer, we can write a macro that renders a field with
|
To make it even nicer, we can write a macro that renders a field with
|
||||||
|
|
@ -95,14 +95,14 @@ Here's an example :file:`_formhelpers.html` template with such a macro:
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
This macro accepts a couple of keyword arguments that are forwarded to
|
This macro accepts a couple of keyword arguments that are forwarded to
|
||||||
WTForm's field function that renders the field for us. The keyword
|
WTForm's field function, which renders the field for us. The keyword
|
||||||
arguments will be inserted as HTML attributes. So for example you can
|
arguments will be inserted as HTML attributes. So, for example, you can
|
||||||
call ``render_field(form.username, class='username')`` to add a class to
|
call ``render_field(form.username, class='username')`` to add a class to
|
||||||
the input element. Note that WTForms returns standard Python unicode
|
the input element. Note that WTForms returns standard Python unicode
|
||||||
strings, so we have to tell Jinja2 that this data is already HTML escaped
|
strings, so we have to tell Jinja2 that this data is already HTML-escaped
|
||||||
with the ``|safe`` filter.
|
with the ``|safe`` filter.
|
||||||
|
|
||||||
Here the :file:`register.html` template for the function we used above which
|
Here is the :file:`register.html` template for the function we used above, which
|
||||||
takes advantage of the :file:`_formhelpers.html` template:
|
takes advantage of the :file:`_formhelpers.html` template:
|
||||||
|
|
||||||
.. sourcecode:: html+jinja
|
.. sourcecode:: html+jinja
|
||||||
|
|
|
||||||
|
|
@ -23,3 +23,6 @@ def add_numbers():
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
return render_template('index.html')
|
return render_template('index.html')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run()
|
||||||
|
|
|
||||||
|
|
@ -54,23 +54,14 @@ else:
|
||||||
|
|
||||||
|
|
||||||
def with_metaclass(meta, *bases):
|
def with_metaclass(meta, *bases):
|
||||||
|
"""Create a base class with a metaclass."""
|
||||||
# This requires a bit of explanation: the basic idea is to make a
|
# This requires a bit of explanation: the basic idea is to make a
|
||||||
# dummy metaclass for one level of class instantiation that replaces
|
# dummy metaclass for one level of class instantiation that replaces
|
||||||
# itself with the actual metaclass. Because of internal type checks
|
# itself with the actual metaclass.
|
||||||
# we also need to make sure that we downgrade the custom metaclass
|
class metaclass(type):
|
||||||
# for one level to something closer to type (that's why __call__ and
|
|
||||||
# __init__ comes back from type etc.).
|
|
||||||
#
|
|
||||||
# This has the advantage over six.with_metaclass in that it does not
|
|
||||||
# introduce dummy classes into the final MRO.
|
|
||||||
class metaclass(meta):
|
|
||||||
__call__ = type.__call__
|
|
||||||
__init__ = type.__init__
|
|
||||||
def __new__(cls, name, this_bases, d):
|
def __new__(cls, name, this_bases, d):
|
||||||
if this_bases is None:
|
|
||||||
return type.__new__(cls, name, (), d)
|
|
||||||
return meta(name, bases, d)
|
return meta(name, bases, d)
|
||||||
return metaclass('temporary_class', None, {})
|
return type.__new__(metaclass, 'temporary_class', (), {})
|
||||||
|
|
||||||
|
|
||||||
# Certain versions of pypy have a bug where clearing the exception stack
|
# Certain versions of pypy have a bug where clearing the exception stack
|
||||||
|
|
|
||||||
|
|
@ -1771,8 +1771,9 @@ class Flask(_PackageBoundObject):
|
||||||
rv = handler(error, endpoint, values)
|
rv = handler(error, endpoint, values)
|
||||||
if rv is not None:
|
if rv is not None:
|
||||||
return rv
|
return rv
|
||||||
except BuildError as error:
|
except BuildError as e:
|
||||||
pass
|
# make error available outside except block (py3)
|
||||||
|
error = e
|
||||||
|
|
||||||
# At this point we want to reraise the exception. If the error is
|
# At this point we want to reraise the exception. If the error is
|
||||||
# still the same one we can reraise it with the original traceback,
|
# still the same one we can reraise it with the original traceback,
|
||||||
|
|
|
||||||
|
|
@ -1069,6 +1069,18 @@ def test_build_error_handler():
|
||||||
assert flask.url_for('spam') == '/test_handler/'
|
assert flask.url_for('spam') == '/test_handler/'
|
||||||
|
|
||||||
|
|
||||||
|
def test_build_error_handler_reraise():
|
||||||
|
app = flask.Flask(__name__)
|
||||||
|
|
||||||
|
# Test a custom handler which reraises the BuildError
|
||||||
|
def handler_raises_build_error(error, endpoint, values):
|
||||||
|
raise error
|
||||||
|
app.url_build_error_handlers.append(handler_raises_build_error)
|
||||||
|
|
||||||
|
with app.test_request_context():
|
||||||
|
pytest.raises(BuildError, flask.url_for, 'not.existing')
|
||||||
|
|
||||||
|
|
||||||
def test_custom_converters():
|
def test_custom_converters():
|
||||||
from werkzeug.routing import BaseConverter
|
from werkzeug.routing import BaseConverter
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue