# 基于類的視圖
基于類的視圖就是實現了response行為的Python類,可以響應request請求。它們提供了在同一個入口響應不同的http方法的方式。比如說如果要定義3個不同的hanler方法,每個方法響應一個http方法,這時就可以用基于類的視圖實現。
## 定義視圖
基于類的視圖需要繼承`HTTPMethodView`,你可以實現所有http方法。如果某個方法未被實現,則會返回`405: Method not allowed`。可以用`app.add_route`注冊視圖,第一個參數必須是視圖類名調用`as_view`方法,第二個參數是url路徑。可以被實現http方法包括: get, post, put, patch, delete。path方法不常見,一般用在有部分修改的資源上。
```py
class TestView(views.HTTPMethodView):
@staticmethod
@bp.middleware('request')
async def print_bp_view_request(request):
print('blue view request middle')
@staticmethod
@bp.middleware('response')
async def print_bp_view_response(request, response):
print('blue view response middle')
async def get(self, request):
return response.json({'type': 'view class'})
bp.add_route(TestView.as_view(), '/view')
```
實現的http方法可以是同步的,也可以是異步的。
## URL參數
如果需要使用URL參數,參照URL路由章節,在方法定義中包含參數即可。
```py
class NameView(HTTPMethodView):
def get(self, request, name):
return text('Hello {}'.format(name))
app.add_route(NameView.as_view(), '/<name>')
```
## 裝飾器
如果需要應用裝飾器,需要定義`decorators`類變量,它們會在`as_view`方法調用后,應用到類中。
```py
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(), '/')
```
## 構建URL
如果希望為HTTPMethodView構建URL,需要將class作為參數傳遞給`url_for`,例如:
```py
@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')
```
## 使用CompositionView
作為`HTTPMethodView`的代替品,可以用`CompositionView`將handler方法移到視圖類外面。每個HTTP方法都可以用外部的handler方法接收,然后用`CompositionView.add`添加到視圖上。第一個參數是HTTP方法列表,比如`['GET', 'POST']`,第二個參數是handler方法。下面這個例子示范了`CompositionView`的兩個使用場景,分別是外部的handler方法和lambda。
```py
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'))
app.add_route(view, '/')
```