# クラスベースビュー

# なぜ使うのか?

# 問題

APIを設計する際の一般的なパターンは、HTTPメソッドに依存する同じエンドポイントに複数の機能を持つことです。

これらのオプションは両方とも機能しますが、優れた設計慣行ではなく、プロジェクトが成長するにつれて時間の経過とともに維持するのが難しい場合があります。

@app.get("/foo")
async def foo_get(request):
    ...
@app.post("/foo")
async def foo_post(request):
    ...
@app.put("/foo")
async def foo_put(request):
    ...
@app.route("/bar", methods=["GET", "POST", "PATCH"])
async def bar(request):
    if request.method == "GET":
        ...
    elif request.method == "POST":
        ...
    elif request.method == "PATCH":
        ...

# 解決策

クラスベースのビューは、単に要求に対する応答動作を実装するクラスです。これらは、同じエンドポイントで異なるHTTPリクエストタイプの処理を区分する方法を提供します。

from sanic.views import HTTPMethodView
class FooBar(HTTPMethodView):
    async def get(self, request):
        ...
    async def post(self, request):
        ...
    async def put(self, request):
        ...
app.add_route(FooBar.as_view(), "/foobar")

# ビューの定義

クラスベースのビューは、HTTPMethodView をサブクラス化する必要があります。その後、対応するHTTPメソッドの名前でクラスメソッドを実装できます。定義されたメソッドを持たない要求を受信すると、405: Method not allowed 応答が生成されます。

エンドポイントにクラスベースのビューを登録するには、app.add_routeメソッドが使用されます。最初の引数は、メソッド as_view が呼び出された定義されたクラスで、2 番目の引数は URL エンドポイントである必要があります。

利用可能な方法は:

  • get
  • post
  • put
  • patch
  • delete
  • head
  • options
from sanic.views import HTTPMethodView
from sanic.response import text
class SimpleView(HTTPMethodView):
  def get(self, request):
      return text("I am get method")
  # You can also use async syntax
  async def post(self, request):
      return text("I am post method")
  def put(self, request):
      return text("I am put method")
  def patch(self, request):
      return text("I am patch method")
  def delete(self, request):
      return text("I am delete method")
app.add_route(SimpleView.as_view(), "/")

# パスパラメーター

ルーティングセクションで説明されているとおりにパスパラメータを使用できます。

class NameView(HTTPMethodView):
  def get(self, request, name):
    return text("Hello {}".format(name))
app.add_route(NameView.as_view(), "/<name>")

# デコレーター

デコレータセクションで説明したように、デコレータを使用してエンドポイントに機能を追加する必要があります。 あなたはCBVと二つ選択肢があります。

  1. ビュー内の 全ての HTTPメソッドに適用する
  2. ビュー内のHTTPメソッドに個別に適用する

オプションがどのように見えるか見てみましょう:

# すべての方法に適用する

クラスにデコレータを追加する場合は、デコレータクラス変数を設定できます。これらは、as_viewが呼び出されるとクラスに適用されます。

class ViewWithDecorator(HTTPMethodView):
  decorators = [some_decorator_here]
  def get(self, request, name):
    return text("Hello I have a decorator")
  def post(self, request, name):
    return text("Hello I also have a decorator")
app.add_route(ViewWithDecorator.as_view(), "/url")

# 個々の方法に適用する

しかし、すべてのメソッドではなく、いくつかのメソッドを飾りたい場合は、ここに示すようにできます。

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")
    @some_decorator_here
    def patch(self, request, name):
        return text("Hello I have a decorator")

# URLを作成

これは、クラス名がエンドポイントの一部であることを除いて、他のURLの生成と同じように機能します。

@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")
MIT Licensed
Copyright © 2018-present Sanic Community Organization

~ Made with ❤️ and ☕️ ~