route decorators custom enpoints #307

Merged
merged 4 commits into from Aug 31, 2011
View
@@ -945,11 +945,15 @@ def show_post(post_id):
subdomain matching is in use.
:param strict_slashes: can be used to disable the strict slashes
setting for this rule. See above.
+ :param endpoint: Since version 0.8 you can also pass the enpoint,
+ it will be used instead of generating the endpoint
+ from the function name.
:param options: other options to be forwarded to the underlying
:class:`~werkzeug.routing.Rule` object.
"""
def decorator(f):
- self.add_url_rule(rule, None, f, **options)
+ endpoint = options.pop("endpoint", None)
+ self.add_url_rule(rule, endpoint, f, **options)
return f
return decorator
View
@@ -157,14 +157,17 @@ def route(self, rule, **options):
:func:`url_for` function is prefixed with the name of the blueprint.
"""
def decorator(f):
- self.add_url_rule(rule, f.__name__, f, **options)
+ endpoint = options.pop("endpoint", f.__name__)
+ self.add_url_rule(rule, endpoint, f, **options)
return f
return decorator
def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
"""Like :meth:`Flask.add_url_rule` but for a blueprint. The endpoint for
the :func:`url_for` function is prefixed with the name of the blueprint.
"""
+ if endpoint:
+ assert '.' not in endpoint, "Blueprint endpoint's should not contain dot's"
self.record(lambda s:
s.add_url_rule(rule, endpoint, view_func, **options))
View
@@ -895,6 +895,32 @@ def foo():
rv = c.post('/foo', data={}, follow_redirects=True)
self.assert_equal(rv.data, 'success')
+ def test_route_decorator_custom_endpoint(self):
+ app = flask.Flask(__name__)
+ app.debug = True
+
+ @app.route('/foo/')
+ def foo():
+ return flask.request.endpoint
+
+ @app.route('/bar/', endpoint='bar')
+ def for_bar():
+ return flask.request.endpoint
+
+ @app.route('/bar/123', endpoint='123')
+ def for_bar_foo():
+ return flask.request.endpoint
+
+ with app.test_request_context():
+ assert flask.url_for('foo') == '/foo/'
+ assert flask.url_for('bar') == '/bar/'
+ assert flask.url_for('123') == '/bar/123'
+
+ c = app.test_client()
+ self.assertEqual(c.get('/foo/').data, 'foo')
+ self.assertEqual(c.get('/bar/').data, 'bar')
+ self.assertEqual(c.get('/bar/123').data, '123')
+
class ContextTestCase(FlaskTestCase):
@@ -415,6 +415,92 @@ def something(page):
self.assert_equal(c.get('/').data, '1')
self.assert_equal(c.get('/page/2').data, '2')
+ def test_route_decorator_custom_endpoint(self):
+
+ bp = flask.Blueprint('bp', __name__)
+
+ @bp.route('/foo')
+ def foo():
+ return flask.request.endpoint
+
+ @bp.route('/bar', endpoint='bar')
+ def foo_bar():
+ return flask.request.endpoint
+
+ @bp.route('/bar/123', endpoint='123')
+ def foo_bar_foo():
+ return flask.request.endpoint
+
+ @bp.route('/bar/foo')
+ def bar_foo():
+ return flask.request.endpoint
+
+ app = flask.Flask(__name__)
+ app.register_blueprint(bp, url_prefix='/py')
+
+ @app.route('/')
+ def index():
+ return flask.request.endpoint
+
+ c = app.test_client()
+ self.assertEqual(c.get('/').data, 'index')
+ self.assertEqual(c.get('/py/foo').data, 'bp.foo')
+ self.assertEqual(c.get('/py/bar').data, 'bp.bar')
+ self.assertEqual(c.get('/py/bar/123').data, 'bp.123')
+ self.assertEqual(c.get('/py/bar/foo').data, 'bp.bar_foo')
+
+ def test_route_decorator_custom_endpoint_with_dots(self):
+ bp = flask.Blueprint('bp', __name__)
+
+ @bp.route('/foo')
+ def foo():
+ return flask.request.endpoint
+
+ try:
+ @bp.route('/bar', endpoint='bar.bar')
+ def foo_bar():
+ return flask.request.endpoint
+ except AssertionError:
+ pass
+ else:
+ raise AssertionError('expected AssertionError not raised')
+
+ try:
+ @bp.route('/bar/123', endpoint='bar.123')
+ def foo_bar_foo():
+ return flask.request.endpoint
+ except AssertionError:
+ pass
+ else:
+ raise AssertionError('expected AssertionError not raised')
+
+ def foo_foo_foo():
+ pass
+
+ self.assertRaises(
+ AssertionError,
+ lambda: bp.add_url_rule(
+ '/bar/123', endpoint='bar.123', view_func=foo_foo_foo
+ )
+ )
+
+ self.assertRaises(
+ AssertionError,
+ bp.route('/bar/123', endpoint='bar.123'),
+ lambda: None
+ )
+
+ app = flask.Flask(__name__)
+ app.register_blueprint(bp, url_prefix='/py')
+
+ c = app.test_client()
+ self.assertEqual(c.get('/py/foo').data, 'bp.foo')
+ # The rule's din't actually made it through
+ rv = c.get('/py/bar')
+ assert rv.status_code == 404
+ rv = c.get('/py/bar/123')
+ assert rv.status_code == 404
+
def suite():
suite = unittest.TestSuite()