all works
This commit is contained in:
parent
7c09ec29f7
commit
f9056099f9
@ -158,3 +158,22 @@ app.blueprint(blueprint_v2)
|
|||||||
|
|
||||||
app.run(host='0.0.0.0', port=8000, debug=True)
|
app.run(host='0.0.0.0', port=8000, debug=True)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## URL Building with `url_for`
|
||||||
|
|
||||||
|
If you wish to generate a URL for a route inside of a blueprint, remember that the endpoint name
|
||||||
|
takes the format `<blueprint_name>.<handler_name>`. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
@blueprint_v1.route('/')
|
||||||
|
async def root(request):
|
||||||
|
url = app.url_for('v1.post_handler', post_id=5)
|
||||||
|
return redirect(url)
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint_v1.route('/post/<post_id>')
|
||||||
|
async def post_handler(request, post_id):
|
||||||
|
return text('Post {} in Blueprint V1'.format(post_id))
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ app.add_route(NameView.as_view(), '/<name>')
|
|||||||
If you want to add any decorators to the class, you can set the `decorators`
|
If you want to add any decorators to the class, you can set the `decorators`
|
||||||
class variable. These will be applied to the class when `as_view` is called.
|
class variable. These will be applied to the class when `as_view` is called.
|
||||||
|
|
||||||
```
|
```python
|
||||||
class ViewWithDecorator(HTTPMethodView):
|
class ViewWithDecorator(HTTPMethodView):
|
||||||
decorators = [some_decorator_here]
|
decorators = [some_decorator_here]
|
||||||
|
|
||||||
@ -77,6 +77,27 @@ class ViewWithDecorator(HTTPMethodView):
|
|||||||
app.add_route(ViewWithDecorator.as_view(), '/url')
|
app.add_route(ViewWithDecorator.as_view(), '/url')
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### URL Building
|
||||||
|
|
||||||
|
If you wish to build a URL for an HTTPMethodView, remember that the class name will be the endpoint
|
||||||
|
that you will pass into `url_for`. For example:
|
||||||
|
|
||||||
|
```python
|
||||||
|
@app.route('/')
|
||||||
|
def index(request):
|
||||||
|
url = app.url_for('SpecialClassView')
|
||||||
|
return redirect(url)
|
||||||
|
|
||||||
|
|
||||||
|
class SpecialClassView(HTTPMethodView):
|
||||||
|
def get(self, request):
|
||||||
|
return text('Hello from the Special Class View!')
|
||||||
|
|
||||||
|
|
||||||
|
app.add_route(SpecialClassView.as_view(), '/special_class_view')
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Using CompositionView
|
## Using CompositionView
|
||||||
|
|
||||||
As an alternative to the `HTTPMethodView`, you can use `CompositionView` to
|
As an alternative to the `HTTPMethodView`, you can use `CompositionView` to
|
||||||
@ -106,3 +127,5 @@ view.add(['POST', 'PUT'], lambda request: text('I am a post/put method'))
|
|||||||
# Use the new view to handle requests to the base URL
|
# Use the new view to handle requests to the base URL
|
||||||
app.add_route(view, '/')
|
app.add_route(view, '/')
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note: currently you cannot build a URL for a CompositionView using `url_for`.
|
||||||
|
@ -119,3 +119,35 @@ app.add_route(handler1, '/test')
|
|||||||
app.add_route(handler2, '/folder/<name>')
|
app.add_route(handler2, '/folder/<name>')
|
||||||
app.add_route(person_handler2, '/person/<name:[A-z]>', methods=['GET'])
|
app.add_route(person_handler2, '/person/<name:[A-z]>', methods=['GET'])
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## URL building with `url_for`.
|
||||||
|
|
||||||
|
Sanic provides a `url_for` method, to generate URLs based on the handler method name. This is useful if you want to avoid hardcoding url paths into your app; instead, you can just reference the handler name. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
@app.route('/')
|
||||||
|
async def index(request):
|
||||||
|
# generate a URL for the endpoint `post_handler`
|
||||||
|
url = app.url_for('post_handler', post_id=5)
|
||||||
|
# the URL is `/posts/5`, redirect to it
|
||||||
|
return redirect(url)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/posts/<post_id>')
|
||||||
|
async def post_handler(request, post_id):
|
||||||
|
return text('Post - {}'.format(post_id))
|
||||||
|
```
|
||||||
|
|
||||||
|
Other things to keep in mind when using `url_for`:
|
||||||
|
|
||||||
|
- Keyword arguments passed to `url_for` that are not request parameters will be included in the URL's query string. For example:
|
||||||
|
```
|
||||||
|
url = app.url_for('post_handler', post_id=5, arg_one='one', arg_two='two')
|
||||||
|
# /posts/5?arg_one=one&arg_two=two
|
||||||
|
```
|
||||||
|
- All valid parameters must be passed to `url_for` to build a URL. If a parameter is not supplied, or if a parameter does not match the specified type, a `URLBuildError` will be thrown.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,3 +17,5 @@ app.static('/the_best.png', '/home/ubuntu/test.png')
|
|||||||
|
|
||||||
app.run(host="0.0.0.0", port=8000)
|
app.run(host="0.0.0.0", port=8000)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note: currently you cannot build a URL for a static file using `url_for`.
|
||||||
|
@ -195,6 +195,26 @@ class Sanic:
|
|||||||
return self.blueprint(*args, **kwargs)
|
return self.blueprint(*args, **kwargs)
|
||||||
|
|
||||||
def url_for(self, view_name: str, **kwargs):
|
def url_for(self, view_name: str, **kwargs):
|
||||||
|
"""Builds a URL based on a view name and the values provided.
|
||||||
|
|
||||||
|
In order to build a URL, all request parameters must be supplied as
|
||||||
|
keyword arguments, and each parameter must pass the test for the
|
||||||
|
specified parameter type. If these conditions are not met, a
|
||||||
|
`URLBuildError` will be thrown.
|
||||||
|
|
||||||
|
Keyword arguments that are not request parameters will be included in
|
||||||
|
the output URL's query string.
|
||||||
|
|
||||||
|
:param view_name: A string referencing the view name
|
||||||
|
:param **kwargs: keys and values that are used to build request
|
||||||
|
parameters and query string arguments.
|
||||||
|
|
||||||
|
:return: the built URL
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
URLBuildError
|
||||||
|
"""
|
||||||
|
# find the route by the supplied view name
|
||||||
uri, route = self.router.find_route_by_view_name(view_name)
|
uri, route = self.router.find_route_by_view_name(view_name)
|
||||||
|
|
||||||
if not uri or not route:
|
if not uri or not route:
|
||||||
@ -203,15 +223,18 @@ class Sanic:
|
|||||||
view_name))
|
view_name))
|
||||||
|
|
||||||
out = uri
|
out = uri
|
||||||
|
|
||||||
|
# find all the parameters we will need to build in the URL
|
||||||
matched_params = re.findall(
|
matched_params = re.findall(
|
||||||
self.router.parameter_pattern, uri)
|
self.router.parameter_pattern, uri)
|
||||||
|
|
||||||
for match in matched_params:
|
for match in matched_params:
|
||||||
name, _type, pattern = self.router.parse_parameter_string(
|
name, _type, pattern = self.router.parse_parameter_string(
|
||||||
match)
|
match)
|
||||||
|
# we only want to match against each individual parameter
|
||||||
specific_pattern = '^{}$'.format(pattern)
|
specific_pattern = '^{}$'.format(pattern)
|
||||||
|
|
||||||
supplied_param = None
|
supplied_param = None
|
||||||
|
|
||||||
if kwargs.get(name):
|
if kwargs.get(name):
|
||||||
supplied_param = kwargs.get(name)
|
supplied_param = kwargs.get(name)
|
||||||
del kwargs[name]
|
del kwargs[name]
|
||||||
@ -221,6 +244,8 @@ class Sanic:
|
|||||||
name))
|
name))
|
||||||
|
|
||||||
supplied_param = str(supplied_param)
|
supplied_param = str(supplied_param)
|
||||||
|
# determine if the parameter supplied by the caller passes the test
|
||||||
|
# in the URL
|
||||||
passes_pattern = re.match(specific_pattern, supplied_param)
|
passes_pattern = re.match(specific_pattern, supplied_param)
|
||||||
|
|
||||||
if not passes_pattern:
|
if not passes_pattern:
|
||||||
@ -236,6 +261,7 @@ class Sanic:
|
|||||||
supplied_param, name, pattern))
|
supplied_param, name, pattern))
|
||||||
raise URLBuildError(msg)
|
raise URLBuildError(msg)
|
||||||
|
|
||||||
|
# replace the parameter in the URL with the supplied value
|
||||||
replacement_regex = '(<{}.*?>)'.format(name)
|
replacement_regex = '(<{}.*?>)'.format(name)
|
||||||
|
|
||||||
out = re.sub(
|
out = re.sub(
|
||||||
|
@ -3,7 +3,7 @@ from urllib.parse import urlsplit, parse_qsl
|
|||||||
|
|
||||||
from sanic import Sanic
|
from sanic import Sanic
|
||||||
from sanic.response import text
|
from sanic.response import text
|
||||||
from sanic.views import HTTPMethodView, CompositionView
|
from sanic.views import HTTPMethodView
|
||||||
from sanic.blueprints import Blueprint
|
from sanic.blueprints import Blueprint
|
||||||
from sanic.utils import sanic_endpoint_test
|
from sanic.utils import sanic_endpoint_test
|
||||||
from sanic.exceptions import URLBuildError
|
from sanic.exceptions import URLBuildError
|
||||||
|
Loading…
x
Reference in New Issue
Block a user