基于 class 的视图#

在设计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")

定义视图#

基于类的视图应该继承自 sanic.views.HTTPMethodView。然后,你可以实现具有相应 HTTP 方法名称的类方法。如果收到没有定义方法的请求,将生成 405:不允许的方法响应。

要在端点上注册基于类的视图,可以使用 app.add_route 方法。第一个参数应该是调用了 as_view 方法的已定义类,第二个参数应该是 URL 端点。

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(), "/")

可用方法有:getpostputpatchdeleteheadoptions

定义路径参数#

class NameView(HTTPMethodView):

  def get(self, request, name):
    return text("Hello {}".format(name))

app.add_route(NameView.as_view(), "/<name>")

生成 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")