forked from orbit-oss/flask
Add a BuildError hook to url_for, #456.
This commit is contained in:
parent
d90f0afe39
commit
bb31188ec3
3 changed files with 46 additions and 0 deletions
20
flask/app.py
20
flask/app.py
|
|
@ -329,6 +329,17 @@ class Flask(_PackageBoundObject):
|
||||||
#: decorator.
|
#: decorator.
|
||||||
self.error_handler_spec = {None: self._error_handlers}
|
self.error_handler_spec = {None: self._error_handlers}
|
||||||
|
|
||||||
|
#: If not `None`, this function is called when :meth:`url_for` raises
|
||||||
|
#: :exc:`~werkzeug.routing.BuildError`, with the call signature::
|
||||||
|
#:
|
||||||
|
#: self.build_error_handler(error, endpoint, **values)
|
||||||
|
#:
|
||||||
|
#: Here, `error` is the instance of `BuildError`, and `endpoint` and
|
||||||
|
#: `**values` are the arguments passed into :meth:`url_for`.
|
||||||
|
#:
|
||||||
|
#: .. versionadded:: 0.9
|
||||||
|
self.build_error_handler = None
|
||||||
|
|
||||||
#: A dictionary with lists of functions that should be called at the
|
#: A dictionary with lists of functions that should be called at the
|
||||||
#: beginning of the request. The key of the dictionary is the name of
|
#: beginning of the request. The key of the dictionary is the name of
|
||||||
#: the blueprint this function is active for, `None` for all requests.
|
#: the blueprint this function is active for, `None` for all requests.
|
||||||
|
|
@ -1473,6 +1484,15 @@ class Flask(_PackageBoundObject):
|
||||||
for func in funcs:
|
for func in funcs:
|
||||||
func(endpoint, values)
|
func(endpoint, values)
|
||||||
|
|
||||||
|
def handle_build_error(self, error, endpoint, **values):
|
||||||
|
"""Handle :class:`~werkzeug.routing.BuildError` on :meth:`url_for`.
|
||||||
|
|
||||||
|
Calls :attr:`build_error_handler` if it is not `None`.
|
||||||
|
"""
|
||||||
|
if self.build_error_handler is None:
|
||||||
|
raise error
|
||||||
|
return self.build_error_handler(error, endpoint, **values)
|
||||||
|
|
||||||
def preprocess_request(self):
|
def preprocess_request(self):
|
||||||
"""Called before the actual request dispatching and will
|
"""Called before the actual request dispatching and will
|
||||||
call every as :meth:`before_request` decorated function.
|
call every as :meth:`before_request` decorated function.
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import mimetypes
|
||||||
from time import time
|
from time import time
|
||||||
from zlib import adler32
|
from zlib import adler32
|
||||||
from threading import RLock
|
from threading import RLock
|
||||||
|
from werkzeug.routing import BuildError
|
||||||
from werkzeug.urls import url_quote
|
from werkzeug.urls import url_quote
|
||||||
|
|
||||||
# try to load the best simplejson implementation available. If JSON
|
# try to load the best simplejson implementation available. If JSON
|
||||||
|
|
@ -214,6 +215,10 @@ def url_for(endpoint, **values):
|
||||||
.. versionadded:: 0.9
|
.. versionadded:: 0.9
|
||||||
The `_anchor` and `_method` parameters were added.
|
The `_anchor` and `_method` parameters were added.
|
||||||
|
|
||||||
|
.. versionadded:: 0.9
|
||||||
|
Calls :meth:`Flask.handle_build_error` on
|
||||||
|
:exc:`~werkzeug.routing.BuildError`.
|
||||||
|
|
||||||
:param endpoint: the endpoint of the URL (name of the function)
|
:param endpoint: the endpoint of the URL (name of the function)
|
||||||
:param values: the variable arguments of the URL rule
|
:param values: the variable arguments of the URL rule
|
||||||
:param _external: if set to `True`, an absolute URL is generated.
|
:param _external: if set to `True`, an absolute URL is generated.
|
||||||
|
|
@ -260,6 +265,15 @@ def url_for(endpoint, **values):
|
||||||
anchor = values.pop('_anchor', None)
|
anchor = values.pop('_anchor', None)
|
||||||
method = values.pop('_method', None)
|
method = values.pop('_method', None)
|
||||||
appctx.app.inject_url_defaults(endpoint, values)
|
appctx.app.inject_url_defaults(endpoint, values)
|
||||||
|
try:
|
||||||
|
rv = url_adapter.build(endpoint, values, method=method,
|
||||||
|
force_external=external)
|
||||||
|
except BuildError, error:
|
||||||
|
values['_external'] = external
|
||||||
|
values['_anchor'] = anchor
|
||||||
|
values['_method'] = method
|
||||||
|
return appctx.app.handle_build_error(error, endpoint, **values)
|
||||||
|
|
||||||
rv = url_adapter.build(endpoint, values, method=method,
|
rv = url_adapter.build(endpoint, values, method=method,
|
||||||
force_external=external)
|
force_external=external)
|
||||||
if anchor is not None:
|
if anchor is not None:
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ from threading import Thread
|
||||||
from flask.testsuite import FlaskTestCase, emits_module_deprecation_warning
|
from flask.testsuite import FlaskTestCase, emits_module_deprecation_warning
|
||||||
from werkzeug.exceptions import BadRequest, NotFound
|
from werkzeug.exceptions import BadRequest, NotFound
|
||||||
from werkzeug.http import parse_date
|
from werkzeug.http import parse_date
|
||||||
|
from werkzeug.routing import BuildError
|
||||||
|
|
||||||
|
|
||||||
class BasicFunctionalityTestCase(FlaskTestCase):
|
class BasicFunctionalityTestCase(FlaskTestCase):
|
||||||
|
|
@ -695,6 +696,17 @@ class BasicFunctionalityTestCase(FlaskTestCase):
|
||||||
self.assert_equal(flask.url_for('hello', name='test x', _external=True),
|
self.assert_equal(flask.url_for('hello', name='test x', _external=True),
|
||||||
'http://localhost/hello/test%20x')
|
'http://localhost/hello/test%20x')
|
||||||
|
|
||||||
|
def test_build_error_handler(self):
|
||||||
|
app = flask.Flask(__name__)
|
||||||
|
with app.test_request_context():
|
||||||
|
self.assertRaises(BuildError, flask.url_for, 'spam')
|
||||||
|
def handler(error, endpoint, **values):
|
||||||
|
# Just a test.
|
||||||
|
return '/test_handler/'
|
||||||
|
app.build_error_handler = handler
|
||||||
|
with app.test_request_context():
|
||||||
|
self.assert_equal(flask.url_for('spam'), '/test_handler/')
|
||||||
|
|
||||||
def test_custom_converters(self):
|
def test_custom_converters(self):
|
||||||
from werkzeug.routing import BaseConverter
|
from werkzeug.routing import BaseConverter
|
||||||
class ListConverter(BaseConverter):
|
class ListConverter(BaseConverter):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue