Merge pull request #3104 from eladm26/adding_models_converter
moving match_request to RequestContext.push to enable ModelConverter
This commit is contained in:
commit
2fa30f6a9e
5 changed files with 52 additions and 26 deletions
|
|
@ -71,6 +71,10 @@ Unreleased
|
||||||
- The ``flask run`` command no longer fails if Python is not built
|
- The ``flask run`` command no longer fails if Python is not built
|
||||||
with SSL support. Using the ``--cert`` option will show an
|
with SSL support. Using the ``--cert`` option will show an
|
||||||
appropriate error message. :issue:`3211`
|
appropriate error message. :issue:`3211`
|
||||||
|
- URL matching now occurs after the request context is pushed, rather
|
||||||
|
than when it's created. This allows custom URL converters to access
|
||||||
|
the app and request contexts, such as to query a database for an id.
|
||||||
|
:issue:`3088`
|
||||||
|
|
||||||
.. _#2935: https://github.com/pallets/flask/issues/2935
|
.. _#2935: https://github.com/pallets/flask/issues/2935
|
||||||
.. _#2957: https://github.com/pallets/flask/issues/2957
|
.. _#2957: https://github.com/pallets/flask/issues/2957
|
||||||
|
|
|
||||||
|
|
@ -314,9 +314,6 @@ class RequestContext(object):
|
||||||
# functions.
|
# functions.
|
||||||
self._after_request_functions = []
|
self._after_request_functions = []
|
||||||
|
|
||||||
if self.url_adapter is not None:
|
|
||||||
self.match_request()
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def g(self):
|
def g(self):
|
||||||
return _app_ctx_stack.top.g
|
return _app_ctx_stack.top.g
|
||||||
|
|
@ -350,8 +347,8 @@ class RequestContext(object):
|
||||||
of the request.
|
of the request.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
url_rule, self.request.view_args = self.url_adapter.match(return_rule=True)
|
result = self.url_adapter.match(return_rule=True)
|
||||||
self.request.url_rule = url_rule
|
self.request.url_rule, self.request.view_args = result
|
||||||
except HTTPException as e:
|
except HTTPException as e:
|
||||||
self.request.routing_exception = e
|
self.request.routing_exception = e
|
||||||
|
|
||||||
|
|
@ -395,6 +392,9 @@ class RequestContext(object):
|
||||||
if self.session is None:
|
if self.session is None:
|
||||||
self.session = session_interface.make_null_session(self.app)
|
self.session = session_interface.make_null_session(self.app)
|
||||||
|
|
||||||
|
if self.url_adapter is not None:
|
||||||
|
self.match_request()
|
||||||
|
|
||||||
def pop(self, exc=_sentinel):
|
def pop(self, exc=_sentinel):
|
||||||
"""Pops the request context and unbinds it by doing that. This will
|
"""Pops the request context and unbinds it by doing that. This will
|
||||||
also trigger the execution of functions registered by the
|
also trigger the execution of functions registered by the
|
||||||
|
|
|
||||||
|
|
@ -1384,26 +1384,6 @@ def test_url_for_passes_special_values_to_build_error_handler(app):
|
||||||
flask.url_for("/")
|
flask.url_for("/")
|
||||||
|
|
||||||
|
|
||||||
def test_custom_converters(app, client):
|
|
||||||
from werkzeug.routing import BaseConverter
|
|
||||||
|
|
||||||
class ListConverter(BaseConverter):
|
|
||||||
def to_python(self, value):
|
|
||||||
return value.split(",")
|
|
||||||
|
|
||||||
def to_url(self, value):
|
|
||||||
base_to_url = super(ListConverter, self).to_url
|
|
||||||
return ",".join(base_to_url(x) for x in value)
|
|
||||||
|
|
||||||
app.url_map.converters["list"] = ListConverter
|
|
||||||
|
|
||||||
@app.route("/<list:args>")
|
|
||||||
def index(args):
|
|
||||||
return "|".join(args)
|
|
||||||
|
|
||||||
assert client.get("/1,2,3").data == b"1|2|3"
|
|
||||||
|
|
||||||
|
|
||||||
def test_static_files(app, client):
|
def test_static_files(app, client):
|
||||||
rv = client.get("/static/index.html")
|
rv = client.get("/static/index.html")
|
||||||
assert rv.status_code == 200
|
assert rv.status_code == 200
|
||||||
|
|
|
||||||
40
tests/test_converters.py
Normal file
40
tests/test_converters.py
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
from werkzeug.routing import BaseConverter
|
||||||
|
|
||||||
|
from flask import has_request_context
|
||||||
|
from flask import url_for
|
||||||
|
|
||||||
|
|
||||||
|
def test_custom_converters(app, client):
|
||||||
|
class ListConverter(BaseConverter):
|
||||||
|
def to_python(self, value):
|
||||||
|
return value.split(",")
|
||||||
|
|
||||||
|
def to_url(self, value):
|
||||||
|
base_to_url = super(ListConverter, self).to_url
|
||||||
|
return ",".join(base_to_url(x) for x in value)
|
||||||
|
|
||||||
|
app.url_map.converters["list"] = ListConverter
|
||||||
|
|
||||||
|
@app.route("/<list:args>")
|
||||||
|
def index(args):
|
||||||
|
return "|".join(args)
|
||||||
|
|
||||||
|
assert client.get("/1,2,3").data == b"1|2|3"
|
||||||
|
|
||||||
|
with app.test_request_context():
|
||||||
|
assert url_for("index", args=[4, 5, 6]) == "/4,5,6"
|
||||||
|
|
||||||
|
|
||||||
|
def test_context_available(app, client):
|
||||||
|
class ContextConverter(BaseConverter):
|
||||||
|
def to_python(self, value):
|
||||||
|
assert has_request_context()
|
||||||
|
return value
|
||||||
|
|
||||||
|
app.url_map.converters["ctx"] = ContextConverter
|
||||||
|
|
||||||
|
@app.route("/<ctx:name>")
|
||||||
|
def index(name):
|
||||||
|
return name
|
||||||
|
|
||||||
|
assert client.get("/admin").data == b"admin"
|
||||||
|
|
@ -153,7 +153,9 @@ def test_blueprint_with_subdomain():
|
||||||
|
|
||||||
ctx = app.test_request_context("/", subdomain="xxx")
|
ctx = app.test_request_context("/", subdomain="xxx")
|
||||||
assert ctx.request.url == "http://xxx.example.com:1234/foo/"
|
assert ctx.request.url == "http://xxx.example.com:1234/foo/"
|
||||||
assert ctx.request.blueprint == bp.name
|
|
||||||
|
with ctx:
|
||||||
|
assert ctx.request.blueprint == bp.name
|
||||||
|
|
||||||
rv = client.get("/", subdomain="xxx")
|
rv = client.get("/", subdomain="xxx")
|
||||||
assert rv.data == b"http://xxx.example.com:1234/foo/"
|
assert rv.data == b"http://xxx.example.com:1234/foo/"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue