sanic/sanic/views.py

110 lines
3.3 KiB
Python
Raw Normal View History

2017-02-16 02:54:00 +00:00
from sanic.constants import HTTP_METHODS
2018-10-18 05:20:16 +01:00
from sanic.exceptions import InvalidUsage
2016-11-26 06:45:08 +00:00
class HTTPMethodView:
"""Simple class based implementation of view for the sanic.
2016-11-28 19:00:39 +00:00
You should implement methods (get, post, put, patch, delete) for the class
2016-11-25 07:29:25 +00:00
to every HTTP method you want to support.
2016-11-28 19:00:39 +00:00
For example:
.. code-block:: python
2017-01-18 21:48:54 +00:00
class DummyView(HTTPMethodView):
def get(self, request, *args, **kwargs):
return text('I am get method')
def put(self, request, *args, **kwargs):
return text('I am put method')
etc.
2016-11-28 19:22:07 +00:00
If someone tries to use a non-implemented method, there will be a
405 response.
2016-11-28 19:00:39 +00:00
If you need any url params just mention them in method definition:
.. code-block:: python
2017-01-18 21:48:54 +00:00
class DummyView(HTTPMethodView):
def get(self, request, my_param_here, *args, **kwargs):
return text('I am get method with %s' % my_param_here)
To add the view into the routing you could use
2017-01-07 04:57:07 +00:00
1) app.add_route(DummyView.as_view(), '/')
2) app.route('/')(DummyView.as_view())
2017-01-07 04:30:23 +00:00
2017-01-07 04:57:07 +00:00
To add any decorator you could set it into decorators variable
"""
2017-01-07 05:13:49 +00:00
decorators = []
2017-01-07 04:30:23 +00:00
def dispatch_request(self, request, *args, **kwargs):
handler = getattr(self, request.method.lower(), None)
2017-02-02 21:24:16 +00:00
return handler(request, *args, **kwargs)
2017-01-07 04:30:23 +00:00
@classmethod
def as_view(cls, *class_args, **class_kwargs):
"""Return view function for use with the routing system, that
dispatches request to appropriate handler method.
2017-01-07 04:30:23 +00:00
"""
2018-10-14 01:55:33 +01:00
2017-01-07 04:30:23 +00:00
def view(*args, **kwargs):
self = view.view_class(*class_args, **class_kwargs)
return self.dispatch_request(*args, **kwargs)
if cls.decorators:
view.__module__ = cls.__module__
for decorator in cls.decorators:
view = decorator(view)
view.view_class = cls
view.__doc__ = cls.__doc__
view.__module__ = cls.__module__
2017-02-02 17:21:14 +00:00
view.__name__ = cls.__name__
2017-01-07 04:30:23 +00:00
return view
def stream(func):
func.is_stream = True
return func
class CompositionView:
"""Simple method-function mapped view for the sanic.
You can add handler functions to methods (get, post, put, patch, delete)
for every HTTP method you want to support.
For example:
view = CompositionView()
view.add(['GET'], lambda request: text('I am get method'))
view.add(['POST', 'PUT'], lambda request: text('I am post/put method'))
etc.
If someone tries to use a non-implemented method, there will be a
405 response.
"""
def __init__(self):
self.handlers = {}
2017-05-07 10:33:47 +01:00
def add(self, methods, handler, stream=False):
if stream:
handler.is_stream = stream
for method in methods:
2017-02-02 21:24:16 +00:00
if method not in HTTP_METHODS:
raise InvalidUsage(
2018-10-14 01:55:33 +01:00
"{} is not a valid HTTP method.".format(method)
)
2017-02-02 21:24:16 +00:00
if method in self.handlers:
2017-02-02 21:24:16 +00:00
raise InvalidUsage(
2018-10-14 01:55:33 +01:00
"Method {} is already registered.".format(method)
)
self.handlers[method] = handler
def __call__(self, request, *args, **kwargs):
2017-02-02 21:24:16 +00:00
handler = self.handlers[request.method.upper()]
return handler(request, *args, **kwargs)