2017-01-20 03:18:52 +00:00
|
|
|
# Class-Based Views
|
2016-11-25 07:10:25 +00:00
|
|
|
|
2017-01-20 03:18:52 +00:00
|
|
|
Class-based views are simply classes which implement response behaviour to
|
|
|
|
requests. They provide a way to compartmentalise handling of different HTTP
|
|
|
|
request types at the same endpoint. Rather than defining and decorating three
|
|
|
|
different handler functions, one for each of an endpoint's supported request
|
|
|
|
type, the endpoint can be assigned a class-based view.
|
|
|
|
|
|
|
|
## Defining views
|
|
|
|
|
|
|
|
A class-based view should subclass `HTTPMethodView`. You can then implement
|
|
|
|
class methods for every HTTP request type you want to support. If a request is
|
|
|
|
received that has no defined method, a `405: Method not allowed` response will
|
|
|
|
be generated.
|
|
|
|
|
|
|
|
To register a class-based view on an endpoint, the `app.add_route` method is
|
|
|
|
used. The first argument should be the defined class with the method `as_view`
|
|
|
|
invoked, and the second should be the URL endpoint.
|
|
|
|
|
|
|
|
The available methods are `get`, `post`, `put`, `patch`, and `delete`. A class
|
|
|
|
using all these methods would look like the following.
|
2016-11-25 07:10:25 +00:00
|
|
|
|
|
|
|
```python
|
|
|
|
from sanic import Sanic
|
2016-11-26 06:44:46 +00:00
|
|
|
from sanic.views import HTTPMethodView
|
2016-12-23 00:42:05 +00:00
|
|
|
from sanic.response import text
|
2016-11-25 07:10:25 +00:00
|
|
|
|
|
|
|
app = Sanic('some_name')
|
|
|
|
|
2016-11-26 06:44:46 +00:00
|
|
|
class SimpleView(HTTPMethodView):
|
2016-11-25 07:10:25 +00:00
|
|
|
|
2016-11-26 06:44:46 +00:00
|
|
|
def get(self, request):
|
2016-11-25 07:10:25 +00:00
|
|
|
return text('I am get method')
|
|
|
|
|
2016-11-26 06:44:46 +00:00
|
|
|
def post(self, request):
|
2016-11-25 07:10:25 +00:00
|
|
|
return text('I am post method')
|
|
|
|
|
2016-11-26 06:44:46 +00:00
|
|
|
def put(self, request):
|
2016-11-25 07:10:25 +00:00
|
|
|
return text('I am put method')
|
|
|
|
|
2016-11-26 06:44:46 +00:00
|
|
|
def patch(self, request):
|
2016-11-25 07:10:25 +00:00
|
|
|
return text('I am patch method')
|
|
|
|
|
2016-11-26 06:44:46 +00:00
|
|
|
def delete(self, request):
|
2016-11-25 07:10:25 +00:00
|
|
|
return text('I am delete method')
|
|
|
|
|
2017-01-07 04:57:07 +00:00
|
|
|
app.add_route(SimpleView.as_view(), '/')
|
2016-11-25 07:10:25 +00:00
|
|
|
|
|
|
|
```
|
|
|
|
|
2017-03-14 18:53:58 +00:00
|
|
|
You can also use `async` syntax.
|
|
|
|
|
|
|
|
```python
|
|
|
|
from sanic import Sanic
|
|
|
|
from sanic.views import HTTPMethodView
|
|
|
|
from sanic.response import text
|
|
|
|
|
|
|
|
app = Sanic('some_name')
|
|
|
|
|
|
|
|
class SimpleAsyncView(HTTPMethodView):
|
|
|
|
|
|
|
|
async def get(self, request):
|
|
|
|
return text('I am async get method')
|
|
|
|
|
|
|
|
app.add_route(SimpleAsyncView.as_view(), '/')
|
|
|
|
|
|
|
|
```
|
|
|
|
|
2017-01-20 03:18:52 +00:00
|
|
|
## URL parameters
|
|
|
|
|
|
|
|
If you need any URL parameters, as discussed in the routing guide, include them
|
|
|
|
in the method definition.
|
2016-11-25 07:10:25 +00:00
|
|
|
|
|
|
|
```python
|
2016-11-26 06:44:46 +00:00
|
|
|
class NameView(HTTPMethodView):
|
2016-11-25 07:10:25 +00:00
|
|
|
|
2016-11-26 06:44:46 +00:00
|
|
|
def get(self, request, name):
|
2016-11-25 07:10:25 +00:00
|
|
|
return text('Hello {}'.format(name))
|
|
|
|
|
2017-01-07 04:57:07 +00:00
|
|
|
app.add_route(NameView.as_view(), '/<name>')
|
|
|
|
```
|
|
|
|
|
2017-01-20 03:18:52 +00:00
|
|
|
## 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.
|
2017-01-07 04:57:07 +00:00
|
|
|
|
2017-02-02 17:52:48 +00:00
|
|
|
```python
|
2017-01-07 04:57:07 +00:00
|
|
|
class ViewWithDecorator(HTTPMethodView):
|
2017-01-07 05:13:49 +00:00
|
|
|
decorators = [some_decorator_here]
|
2017-01-07 04:57:07 +00:00
|
|
|
|
|
|
|
def get(self, request, name):
|
|
|
|
return text('Hello I have a decorator')
|
|
|
|
|
2018-01-19 08:20:07 +00:00
|
|
|
def post(self, request, name):
|
|
|
|
return text("Hello I also have a decorator")
|
|
|
|
|
2017-01-07 04:57:07 +00:00
|
|
|
app.add_route(ViewWithDecorator.as_view(), '/url')
|
2016-11-25 07:10:25 +00:00
|
|
|
```
|
2017-01-20 03:18:52 +00:00
|
|
|
|
2018-01-19 08:20:07 +00:00
|
|
|
But if you just want to decorator some functions and not all functions, you can use as followed.
|
|
|
|
|
|
|
|
```python
|
|
|
|
class ViewWithSomeDecorator(HTTPMethodView):
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
@some_decorator_here
|
|
|
|
def get(request, name):
|
|
|
|
return text("Hello I have a decorator")
|
|
|
|
|
|
|
|
def post(self, request, name):
|
|
|
|
return text("Hello I don't have any decorators")
|
|
|
|
```
|
|
|
|
|
|
|
|
## URL Building
|
2017-02-02 17:52:48 +00:00
|
|
|
|
|
|
|
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')
|
|
|
|
```
|
|
|
|
|
|
|
|
|
2017-01-26 22:52:41 +00:00
|
|
|
## Using CompositionView
|
|
|
|
|
|
|
|
As an alternative to the `HTTPMethodView`, you can use `CompositionView` to
|
|
|
|
move handler functions outside of the view class.
|
|
|
|
|
|
|
|
Handler functions for each supported HTTP method are defined elsewhere in the
|
|
|
|
source, and then added to the view using the `CompositionView.add` method. The
|
|
|
|
first parameter is a list of HTTP methods to handle (e.g. `['GET', 'POST']`),
|
|
|
|
and the second is the handler function. The following example shows
|
|
|
|
`CompositionView` usage with both an external handler function and an inline
|
|
|
|
lambda:
|
|
|
|
|
|
|
|
```python
|
|
|
|
from sanic import Sanic
|
|
|
|
from sanic.views import CompositionView
|
|
|
|
from sanic.response import text
|
|
|
|
|
|
|
|
app = Sanic(__name__)
|
|
|
|
|
|
|
|
def get_handler(request):
|
|
|
|
return text('I am a get method')
|
|
|
|
|
|
|
|
view = CompositionView()
|
|
|
|
view.add(['GET'], get_handler)
|
|
|
|
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, '/')
|
|
|
|
```
|
2017-02-02 17:52:48 +00:00
|
|
|
|
2017-03-14 18:53:58 +00:00
|
|
|
Note: currently you cannot build a URL for a CompositionView using `url_for`.
|