diff --git a/docs/sanic/blueprints.md b/docs/sanic/blueprints.md index 120aa1dd..02d387b2 100644 --- a/docs/sanic/blueprints.md +++ b/docs/sanic/blueprints.md @@ -131,8 +131,8 @@ can be used to implement our API versioning scheme. from sanic.response import text from sanic import Blueprint -blueprint_v1 = Blueprint('v1') -blueprint_v2 = Blueprint('v2') +blueprint_v1 = Blueprint('v1', url_prefix='/v1') +blueprint_v2 = Blueprint('v2', url_prefix='/v2') @blueprint_v1.route('/') async def api_v1_root(request): diff --git a/sanic/blueprints.py b/sanic/blueprints.py index 64a37da0..155d187b 100644 --- a/sanic/blueprints.py +++ b/sanic/blueprints.py @@ -1,5 +1,7 @@ from collections import defaultdict, namedtuple +from sanic.constants import HTTP_METHODS +from sanic.views import CompositionView FutureRoute = namedtuple('Route', ['handler', 'uri', 'methods', 'host']) FutureListener = namedtuple('Listener', ['handler', 'uri', 'methods', 'host']) @@ -82,15 +84,28 @@ class Blueprint: return handler return decorator - def add_route(self, handler, uri, methods=None, host=None): + def add_route(self, handler, uri, methods=frozenset({'GET'}), host=None): """ Creates a blueprint route from a function. - :param handler: Function to handle uri request. + :param handler: Function for handling uri requests. Accepts function, + or class instance with a view_class method. :param uri: Endpoint at which the route will be accessible. :param methods: List of acceptable HTTP methods. + :return: function or class instance """ - route = FutureRoute(handler, uri, methods, host) - self.routes.append(route) + # Handle HTTPMethodView differently + if hasattr(handler, 'view_class'): + methods = set() + + for method in HTTP_METHODS: + if getattr(handler.view_class, method.lower(), None): + methods.add(method) + + # handle composition view differently + if isinstance(handler, CompositionView): + methods = handler.handlers.keys() + + self.route(uri=uri, methods=methods, host=host)(handler) return handler def listener(self, event):