-
-
Notifications
You must be signed in to change notification settings - Fork 930
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Renaming asgi_application, implementing CBV pattern, add_route method on router * Refactor view to allow both sync/async methods * Type hints for CBV * Implement asgi decorator method directly in view class, remove classmethod * Refactor CBV, remove router add_route method in favor of App.add_route method, tests, documentation * Include tests * Add support for class-based views
- Loading branch information
1 parent
4549d62
commit 0693a8f
Showing
5 changed files
with
118 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
|
||
Starlette includes a `View` class that provides a class-based view pattern which | ||
handles HTTP method dispatching. | ||
|
||
The `View` class can be used as an other ASGI application: | ||
|
||
```python | ||
from starlette.response import PlainTextResponse | ||
from starlette.views import View | ||
|
||
|
||
class App(View): | ||
async def get(self, request): | ||
return PlainTextResponse(f"Hello, world!") | ||
``` | ||
|
||
If you're using a Starlette application instance to handle routing, you can | ||
dispatch to a View class by using the `@app.route()` decorator, or the | ||
`app.add_route()` function. Make sure to dispatch to the class itself, rather | ||
than to an instance of the class: | ||
|
||
```python | ||
from starlette.app import App | ||
from starlette.response import PlainTextResponse | ||
from starlette.views import View | ||
|
||
|
||
app = App() | ||
|
||
|
||
@app.route("/") | ||
class Homepage(View): | ||
async def get(self, request): | ||
return PlainTextResponse(f"Hello, world!") | ||
|
||
|
||
@app.route("/{username}") | ||
class User(View): | ||
async def get(self, request, username): | ||
return PlainTextResponse(f"Hello, {username}") | ||
``` | ||
|
||
Class-based views will respond with "406 Method not allowed" responses for any | ||
request methods which do not map to a corresponding handler. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from starlette.request import Request | ||
from starlette.response import Response, PlainTextResponse | ||
from starlette.types import Receive, Send, Scope | ||
|
||
|
||
class View: | ||
def __init__(self, scope: Scope): | ||
self.scope = scope | ||
|
||
async def __call__(self, receive: Receive, send: Send): | ||
request = Request(self.scope, receive=receive) | ||
kwargs = self.scope.get("kwargs", {}) | ||
response = await self.dispatch(request, **kwargs) | ||
await response(receive, send) | ||
|
||
async def dispatch(self, request: Request, **kwargs) -> Response: | ||
handler_name = "get" if request.method == "HEAD" else request.method.lower() | ||
handler = getattr(self, handler_name, self.method_not_allowed) | ||
return await handler(request, **kwargs) | ||
|
||
async def method_not_allowed(self, request: Request, **kwargs) -> Response: | ||
return PlainTextResponse("Method not allowed", 406) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import pytest | ||
from starlette import App | ||
from starlette.views import View | ||
from starlette.response import PlainTextResponse | ||
from starlette.testclient import TestClient | ||
|
||
|
||
app = App() | ||
|
||
|
||
@app.route("/") | ||
@app.route("/{username}") | ||
class Homepage(View): | ||
async def get(self, request, username=None): | ||
if username is None: | ||
return PlainTextResponse("Hello, world!") | ||
return PlainTextResponse(f"Hello, {username}!") | ||
|
||
|
||
client = TestClient(app) | ||
|
||
|
||
def test_route(): | ||
response = client.get("/") | ||
assert response.status_code == 200 | ||
assert response.text == "Hello, world!" | ||
|
||
|
||
def test_route_kwargs(): | ||
response = client.get("/tomchristie") | ||
assert response.status_code == 200 | ||
assert response.text == "Hello, tomchristie!" | ||
|
||
|
||
def test_route_method(): | ||
response = client.post("/") | ||
assert response.status_code == 406 | ||
assert response.text == "Method not allowed" |