all works
This commit is contained in:
		| @@ -158,3 +158,22 @@ app.blueprint(blueprint_v2) | ||||
|  | ||||
| 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` | ||||
| class variable. These will be applied to the class when `as_view` is called. | ||||
|  | ||||
| ``` | ||||
| ```python | ||||
| class ViewWithDecorator(HTTPMethodView): | ||||
|   decorators = [some_decorator_here] | ||||
|  | ||||
| @@ -77,6 +77,27 @@ class ViewWithDecorator(HTTPMethodView): | ||||
| 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 | ||||
|  | ||||
| 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 | ||||
| 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(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) | ||||
| ``` | ||||
|  | ||||
| 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) | ||||
|  | ||||
|     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) | ||||
|  | ||||
|         if not uri or not route: | ||||
| @@ -203,15 +223,18 @@ class Sanic: | ||||
|                         view_name)) | ||||
|  | ||||
|         out = uri | ||||
|  | ||||
|         # find all the parameters we will need to build in the URL | ||||
|         matched_params = re.findall( | ||||
|             self.router.parameter_pattern, uri) | ||||
|  | ||||
|         for match in matched_params: | ||||
|             name, _type, pattern = self.router.parse_parameter_string( | ||||
|                 match) | ||||
|             # we only want to match against each individual parameter | ||||
|             specific_pattern = '^{}$'.format(pattern) | ||||
|  | ||||
|             supplied_param = None | ||||
|  | ||||
|             if kwargs.get(name): | ||||
|                 supplied_param = kwargs.get(name) | ||||
|                 del kwargs[name] | ||||
| @@ -221,6 +244,8 @@ class Sanic: | ||||
|                         name)) | ||||
|  | ||||
|             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) | ||||
|  | ||||
|             if not passes_pattern: | ||||
| @@ -236,6 +261,7 @@ class Sanic: | ||||
|                             supplied_param, name, pattern)) | ||||
|                 raise URLBuildError(msg) | ||||
|  | ||||
|             # replace the parameter in the URL with the supplied value | ||||
|             replacement_regex = '(<{}.*?>)'.format(name) | ||||
|  | ||||
|             out = re.sub( | ||||
|   | ||||
| @@ -3,7 +3,7 @@ from urllib.parse import urlsplit, parse_qsl | ||||
|  | ||||
| from sanic import Sanic | ||||
| from sanic.response import text | ||||
| from sanic.views import HTTPMethodView, CompositionView | ||||
| from sanic.views import HTTPMethodView | ||||
| from sanic.blueprints import Blueprint | ||||
| from sanic.utils import sanic_endpoint_test | ||||
| from sanic.exceptions import URLBuildError | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Suby Raman
					Suby Raman