Merge pull request #3104 from eladm26/adding_models_converter

moving match_request to RequestContext.push to enable ModelConverter
This commit is contained in:
David Lord 2019-06-13 12:46:53 -07:00 committed by GitHub
commit 2fa30f6a9e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 52 additions and 26 deletions

View file

@ -71,6 +71,10 @@ Unreleased
- The ``flask run`` command no longer fails if Python is not built
with SSL support. Using the ``--cert`` option will show an
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
.. _#2957: https://github.com/pallets/flask/issues/2957

View file

@ -314,9 +314,6 @@ class RequestContext(object):
# functions.
self._after_request_functions = []
if self.url_adapter is not None:
self.match_request()
@property
def g(self):
return _app_ctx_stack.top.g
@ -350,8 +347,8 @@ class RequestContext(object):
of the request.
"""
try:
url_rule, self.request.view_args = self.url_adapter.match(return_rule=True)
self.request.url_rule = url_rule
result = self.url_adapter.match(return_rule=True)
self.request.url_rule, self.request.view_args = result
except HTTPException as e:
self.request.routing_exception = e
@ -395,6 +392,9 @@ class RequestContext(object):
if self.session is None:
self.session = session_interface.make_null_session(self.app)
if self.url_adapter is not None:
self.match_request()
def pop(self, exc=_sentinel):
"""Pops the request context and unbinds it by doing that. This will
also trigger the execution of functions registered by the

View file

@ -1384,26 +1384,6 @@ def test_url_for_passes_special_values_to_build_error_handler(app):
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):
rv = client.get("/static/index.html")
assert rv.status_code == 200

40
tests/test_converters.py Normal file
View 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"

View file

@ -153,7 +153,9 @@ def test_blueprint_with_subdomain():
ctx = app.test_request_context("/", subdomain="xxx")
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")
assert rv.data == b"http://xxx.example.com:1234/foo/"