Merge pull request #274 from AntonDnepr/cbw_fixes

Class based views fixes
This commit is contained in:
Eli Uriegas 2017-01-07 10:07:14 -06:00 committed by GitHub
commit ebc8d7168a
3 changed files with 92 additions and 14 deletions

View File

@ -28,7 +28,7 @@ class SimpleView(HTTPMethodView):
def delete(self, request): def delete(self, request):
return text('I am delete method') return text('I am delete method')
app.add_route(SimpleView(), '/') app.add_route(SimpleView.as_view(), '/')
``` ```
@ -40,6 +40,19 @@ class NameView(HTTPMethodView):
def get(self, request, name): def get(self, request, name):
return text('Hello {}'.format(name)) return text('Hello {}'.format(name))
app.add_route(NameView(), '/<name>') app.add_route(NameView.as_view(), '/<name>')
```
If you want to add decorator for class, you could set decorators variable
```
class ViewWithDecorator(HTTPMethodView):
decorators = [some_decorator_here]
def get(self, request, name):
return text('Hello I have a decorator')
app.add_route(ViewWithDecorator.as_view(), '/url')
``` ```

View File

@ -7,7 +7,7 @@ class HTTPMethodView:
to every HTTP method you want to support. to every HTTP method you want to support.
For example: For example:
class DummyView(View): class DummyView(HTTPMethodView):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
return text('I am get method') return text('I am get method')
@ -20,20 +20,44 @@ class HTTPMethodView:
405 response. 405 response.
If you need any url params just mention them in method definition: If you need any url params just mention them in method definition:
class DummyView(View): class DummyView(HTTPMethodView):
def get(self, request, my_param_here, *args, **kwargs): def get(self, request, my_param_here, *args, **kwargs):
return text('I am get method with %s' % my_param_here) return text('I am get method with %s' % my_param_here)
To add the view into the routing you could use To add the view into the routing you could use
1) app.add_route(DummyView(), '/') 1) app.add_route(DummyView.as_view(), '/')
2) app.route('/')(DummyView()) 2) app.route('/')(DummyView.as_view())
To add any decorator you could set it into decorators variable
""" """
def __call__(self, request, *args, **kwargs): decorators = []
def dispatch_request(self, request, *args, **kwargs):
handler = getattr(self, request.method.lower(), None) handler = getattr(self, request.method.lower(), None)
if handler: if handler:
return handler(request, *args, **kwargs) return handler(request, *args, **kwargs)
raise InvalidUsage( raise InvalidUsage(
'Method {} not allowed for URL {}'.format( 'Method {} not allowed for URL {}'.format(
request.method, request.url), status_code=405) request.method, request.url), status_code=405)
@classmethod
def as_view(cls, *class_args, **class_kwargs):
""" Converts the class into an actual view function that can be used
with the routing system.
"""
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__
return view

View File

@ -26,7 +26,7 @@ def test_methods():
def delete(self, request): def delete(self, request):
return text('I am delete method') return text('I am delete method')
app.add_route(DummyView(), '/') app.add_route(DummyView.as_view(), '/')
request, response = sanic_endpoint_test(app, method="get") request, response = sanic_endpoint_test(app, method="get")
assert response.text == 'I am get method' assert response.text == 'I am get method'
@ -48,7 +48,7 @@ def test_unexisting_methods():
def get(self, request): def get(self, request):
return text('I am get method') return text('I am get method')
app.add_route(DummyView(), '/') app.add_route(DummyView.as_view(), '/')
request, response = sanic_endpoint_test(app, method="get") request, response = sanic_endpoint_test(app, method="get")
assert response.text == 'I am get method' assert response.text == 'I am get method'
request, response = sanic_endpoint_test(app, method="post") request, response = sanic_endpoint_test(app, method="post")
@ -63,7 +63,7 @@ def test_argument_methods():
def get(self, request, my_param_here): def get(self, request, my_param_here):
return text('I am get method with %s' % my_param_here) return text('I am get method with %s' % my_param_here)
app.add_route(DummyView(), '/<my_param_here>') app.add_route(DummyView.as_view(), '/<my_param_here>')
request, response = sanic_endpoint_test(app, uri='/test123') request, response = sanic_endpoint_test(app, uri='/test123')
@ -79,7 +79,7 @@ def test_with_bp():
def get(self, request): def get(self, request):
return text('I am get method') return text('I am get method')
bp.add_route(DummyView(), '/') bp.add_route(DummyView.as_view(), '/')
app.blueprint(bp) app.blueprint(bp)
request, response = sanic_endpoint_test(app) request, response = sanic_endpoint_test(app)
@ -96,7 +96,7 @@ def test_with_bp_with_url_prefix():
def get(self, request): def get(self, request):
return text('I am get method') return text('I am get method')
bp.add_route(DummyView(), '/') bp.add_route(DummyView.as_view(), '/')
app.blueprint(bp) app.blueprint(bp)
request, response = sanic_endpoint_test(app, uri='/test1/') request, response = sanic_endpoint_test(app, uri='/test1/')
@ -112,7 +112,7 @@ def test_with_middleware():
def get(self, request): def get(self, request):
return text('I am get method') return text('I am get method')
app.add_route(DummyView(), '/') app.add_route(DummyView.as_view(), '/')
results = [] results = []
@ -145,7 +145,7 @@ def test_with_middleware_response():
def get(self, request): def get(self, request):
return text('I am get method') return text('I am get method')
app.add_route(DummyView(), '/') app.add_route(DummyView.as_view(), '/')
request, response = sanic_endpoint_test(app) request, response = sanic_endpoint_test(app)
@ -153,3 +153,44 @@ def test_with_middleware_response():
assert type(results[0]) is Request assert type(results[0]) is Request
assert type(results[1]) is Request assert type(results[1]) is Request
assert issubclass(type(results[2]), HTTPResponse) assert issubclass(type(results[2]), HTTPResponse)
def test_with_custom_class_methods():
app = Sanic('test_with_custom_class_methods')
class DummyView(HTTPMethodView):
global_var = 0
def _iternal_method(self):
self.global_var += 10
def get(self, request):
self._iternal_method()
return text('I am get method and global var is {}'.format(self.global_var))
app.add_route(DummyView.as_view(), '/')
request, response = sanic_endpoint_test(app, method="get")
assert response.text == 'I am get method and global var is 10'
def test_with_decorator():
app = Sanic('test_with_decorator')
results = []
def stupid_decorator(view):
def decorator(*args, **kwargs):
results.append(1)
return view(*args, **kwargs)
return decorator
class DummyView(HTTPMethodView):
decorators = [stupid_decorator]
def get(self, request):
return text('I am get method')
app.add_route(DummyView.as_view(), '/')
request, response = sanic_endpoint_test(app, method="get")
assert response.text == 'I am get method'
assert results[0] == 1