From Flask¶
ASGI 與 WSGI¶
Flask 是一個 WSGI 框架,而 Litestar 則是使用現代的 ASGI 標準建置的。兩者之間的一個關鍵區別在於 ASGI 是以異步(async)為核心設計的。
While Flask has added support for async/await, it remains synchronous at its core;
The async support in Flask is limited to individual endpoints.
What this means is that while you can use async def to define endpoints in Flask,
they will not run concurrently - requests will still be processed one at a time.
Flask handles asynchronous endpoints by creating an event loop for each request, run the
endpoint function in it, and then return its result.
另一方面,ASGI 則完全相反;它在中心事件迴圈中執行所有內容。Litestar 接著透過在事件迴圈上以非阻塞方式執行同步函式,進而提供對同步函式的支援。這意味著同步和非同步程式碼都能同時並行執行。
Routing¶
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "Index Page"
@app.route("/hello")
def hello():
return "Hello, World"
from litestar import Litestar, get
@get("/")
def index() -> str:
return "Index Page"
@get("/hello")
def hello() -> str:
return "Hello, World"
app = Litestar([index, hello])
路徑參數¶
from flask import Flask
app = Flask(__name__)
@app.route("/user/<username>")
def show_user_profile(username):
return f"User {username}"
@app.route("/post/<int:post_id>")
def show_post(post_id):
return f"Post {post_id}"
@app.route("/path/<path:subpath>")
def show_subpath(subpath):
return f"Subpath {subpath}"
from litestar import Litestar, get
from pathlib import Path
@get("/user/{username:str}")
def show_user_profile(username: str) -> str:
return f"User {username}"
@get("/post/{post_id:int}")
def show_post(post_id: int) -> str:
return f"Post {post_id}"
@get("/path/{subpath:path}")
def show_subpath(subpath: Path) -> str:
return f"Subpath {subpath}"
app = Litestar([show_user_profile, show_post, show_subpath])
請求物件¶
In Flask, the current request can be accessed through a global request variable. In Litestar,
the request can be accessed through an optional parameter in the handler function.
from flask import Flask, request
app = Flask(__name__)
@app.get("/")
def index():
print(request.method)
from litestar import get, Request
@get("/")
def index(request: Request) -> None:
print(request.method)
請求方法¶
Flask |
Litestar |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Use |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Static files¶
Like Flask, Litestar also has capabilities for serving static files, but while Flask
will automatically serve files from a static folder, this has to be configured explicitly
in Litestar.
from litestar import Litestar
from litestar.static_files import create_static_files_router
app = Litestar(route_handlers=[
create_static_files_router(path="/static", directories=["assets"]),
])
Templates¶
Flask comes with the Jinja templating
engine built-in. You can use Jinja with Litestar as well, but you’ll need to install it
explicitly. You can do by installing Litestar with pip install 'litestar[jinja]'.
In addition to Jinja, Litestar supports Mako and Minijinja templates as well.
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/hello/<name>")
def hello(name):
return render_template("hello.html", name=name)
from litestar import Litestar, get
from litestar.contrib.jinja import JinjaTemplateEngine
from litestar.response import Template
from litestar.template.config import TemplateConfig
@get("/hello/{name:str}")
def hello(name: str) -> Template:
return Template(response_name="hello.html", context={"name": name})
app = Litestar(
[hello],
template_config=TemplateConfig(directory="templates", engine=JinjaTemplateEngine),
)
Redirects¶
For redirects, instead of redirect use Redirect:
from flask import Flask, redirect, url_for
app = Flask(__name__)
@app.get("/")
def index():
return "hello"
@app.get("/hello")
def hello():
return redirect(url_for("index"))
from litestar import Litestar, get
from litestar.response import Redirect
@get("/")
def index() -> str:
return "hello"
@get("/hello")
def hello() -> Redirect:
return Redirect(path="/")
app = Litestar([index, hello])
Raising HTTP errors¶
Instead of using the abort function, raise an HTTPException:
from flask import Flask, abort
app = Flask(__name__)
@app.get("/")
def index():
abort(400, "this did not work")
from litestar import Litestar, get
from litestar.exceptions import HTTPException
@get("/")
def index() -> None:
raise HTTPException(status_code=400, detail="this did not work")
app = Litestar([index])
也參考
To learn more about exceptions, check out this chapter in the documentation:
Setting status codes¶
from flask import Flask
app = Flask(__name__)
@app.get("/")
def index():
return "not found", 404
from litestar import Litestar, get, Response
@get("/static", status_code=404)
def static_status() -> str:
return "not found"
@get("/dynamic")
def dynamic_status() -> Response[str]:
return Response("not found", status_code=404)
app = Litestar([static_status, dynamic_status])
序列化¶
Flask uses a mix of explicit conversion (such as jsonify) and inference (i.e. the type
of the returned data) to determine how data should be serialized. Litestar instead assumes
the data returned is intended to be serialized into JSON and will do so unless told otherwise.
from flask import Flask, Response
app = Flask(__name__)
@app.get("/json")
def get_json():
return {"hello": "world"}
@app.get("/text")
def get_text():
return "hello, world!"
@app.get("/html")
def get_html():
return Response("<strong>hello, world</strong>", mimetype="text/html")
from litestar import Litestar, get, MediaType
@get("/json")
def get_json() -> dict[str, str]:
return {"hello": "world"}
@get("/text", media_type=MediaType.TEXT)
def get_text() -> str:
return "hello, world"
@get("/html", media_type=MediaType.HTML)
def get_html() -> str:
return "<strong>hello, world</strong>"
app = Litestar([get_json, get_text, get_html])
Error handling¶
from flask import Flask
from werkzeug.exceptions import HTTPException
app = Flask(__name__)
@app.errorhandler(HTTPException)
def handle_exception(e): ...
from litestar import Litestar, Request, Response
from litestar.exceptions import HTTPException
def handle_exception(request: Request, exception: Exception) -> Response: ...
app = Litestar([], exception_handlers={HTTPException: handle_exception})
也參考
To learn more about exception handling, check out this chapter in the documentation: