Skip to content

Commit 02ef5f5

Browse files
authored
add Quart asgi template (#1138)
1 parent 965c5b3 commit 02ef5f5

File tree

7 files changed

+148
-1
lines changed

7 files changed

+148
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ Let Piccolo scaffold you an ASGI web app, using Piccolo as the ORM:
9494
piccolo asgi new
9595
```
9696

97-
[Starlette](https://www.starlette.io/), [FastAPI](https://fastapi.tiangolo.com/), [BlackSheep](https://www.neoteroi.dev/blacksheep/), [Litestar](https://litestar.dev/), [Esmerald](https://esmerald.dev/) and [Lilya](https://lilya.dev) are currently supported.
97+
[Starlette](https://www.starlette.io/), [FastAPI](https://fastapi.tiangolo.com/), [BlackSheep](https://www.neoteroi.dev/blacksheep/), [Litestar](https://litestar.dev/), [Esmerald](https://esmerald.dev/), [Lilya](https://lilya.dev) and [Quart](https://quart.palletsprojects.com/en/latest/) are currently supported.
9898

9999
## Are you a Django user?
100100

piccolo/apps/asgi/commands/new.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"litestar": ["litestar"],
1818
"esmerald": ["esmerald"],
1919
"lilya": ["lilya"],
20+
"quart": ["quart", "quart_schema"],
2021
}
2122
ROUTERS = list(ROUTER_DEPENDENCIES.keys())
2223

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import typing as t
2+
from http import HTTPStatus
3+
4+
from hypercorn.middleware import DispatcherMiddleware
5+
from piccolo.engine import engine_finder
6+
from piccolo_admin.endpoints import create_admin
7+
from piccolo_api.crud.serializers import create_pydantic_model
8+
from quart import Quart
9+
from quart_schema import (
10+
Info,
11+
QuartSchema,
12+
hide,
13+
tag,
14+
validate_request,
15+
validate_response,
16+
)
17+
18+
from home.endpoints import index
19+
from home.piccolo_app import APP_CONFIG
20+
from home.tables import Task
21+
22+
23+
app = Quart(__name__, static_folder="static")
24+
QuartSchema(app, info=Info(title="Quart API", version="0.1.0"))
25+
26+
27+
TaskModelIn: t.Any = create_pydantic_model(
28+
table=Task,
29+
model_name="TaskModelIn",
30+
)
31+
TaskModelOut: t.Any = create_pydantic_model(
32+
table=Task,
33+
include_default_columns=True,
34+
model_name="TaskModelOut",
35+
)
36+
37+
38+
@app.get("/")
39+
@hide
40+
def home():
41+
return index()
42+
43+
44+
@app.get("/tasks/")
45+
@validate_response(t.List[TaskModelOut])
46+
@tag(["Task"])
47+
async def tasks():
48+
return await Task.select().order_by(Task._meta.primary_key, ascending=False)
49+
50+
51+
@app.post("/tasks/")
52+
@validate_request(TaskModelIn)
53+
@validate_response(TaskModelOut)
54+
@tag(["Task"])
55+
async def create_task(data: TaskModelIn):
56+
task = Task(**data.model_dump())
57+
await task.save()
58+
return task.to_dict(), HTTPStatus.CREATED
59+
60+
61+
@app.put("/tasks/<int:task_id>/")
62+
@validate_request(TaskModelIn)
63+
@validate_response(TaskModelOut)
64+
@tag(["Task"])
65+
async def update_task(task_id: int, data: TaskModelIn):
66+
task = await Task.objects().get(Task._meta.primary_key == task_id)
67+
if not task:
68+
return {}, HTTPStatus.NOT_FOUND
69+
70+
for key, value in data.model_dump().items():
71+
setattr(task, key, value)
72+
73+
await task.save()
74+
75+
return task.to_dict(), HTTPStatus.OK
76+
77+
78+
@app.delete("/tasks/<int:task_id>/")
79+
@validate_response(TaskModelOut)
80+
@tag(["Task"])
81+
async def delete_task(task_id: int):
82+
task = await Task.objects().get(Task._meta.primary_key == task_id)
83+
if not task:
84+
return {}, HTTPStatus.NOT_FOUND
85+
86+
await task.remove()
87+
88+
return {}, HTTPStatus.OK
89+
90+
91+
@app.before_serving
92+
async def open_database_connection_pool():
93+
try:
94+
engine = engine_finder()
95+
await engine.start_connection_pool()
96+
except Exception:
97+
print("Unable to connect to the database")
98+
99+
100+
@app.after_serving
101+
async def close_database_connection_pool():
102+
try:
103+
engine = engine_finder()
104+
await engine.close_connection_pool()
105+
except Exception:
106+
print("Unable to connect to the database")
107+
108+
109+
# enable the admin application using DispatcherMiddleware
110+
app = DispatcherMiddleware( # type: ignore
111+
{
112+
"/admin": create_admin(
113+
tables=APP_CONFIG.table_classes,
114+
# Required when running under HTTPS:
115+
# allowed_hosts=['my_site.com']
116+
),
117+
"": app,
118+
}
119+
)

piccolo/apps/asgi/commands/templates/app/app.py.jinja

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,6 @@
1010
{% include '_esmerald_app.py.jinja' %}
1111
{% elif router == 'lilya' %}
1212
{% include '_lilya_app.py.jinja' %}
13+
{% elif router == 'quart' %}
14+
{% include '_quart_app.py.jinja' %}
1315
{% endif %}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import os
2+
3+
import jinja2
4+
5+
from quart import Response
6+
7+
ENVIRONMENT = jinja2.Environment(
8+
loader=jinja2.FileSystemLoader(
9+
searchpath=os.path.join(os.path.dirname(__file__), "templates")
10+
)
11+
)
12+
13+
14+
def index():
15+
template = ENVIRONMENT.get_template("home.html.jinja")
16+
content = template.render(title="Piccolo + ASGI")
17+
return Response(content)
18+

piccolo/apps/asgi/commands/templates/app/home/endpoints.py.jinja

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@
88
{% include '_esmerald_endpoints.py.jinja' %}
99
{% elif router == 'lilya' %}
1010
{% include '_lilya_endpoints.py.jinja' %}
11+
{% elif router == 'quart' %}
12+
{% include '_quart_endpoints.py.jinja' %}
1113
{% endif %}

piccolo/apps/asgi/commands/templates/app/home/templates/home.html.jinja_raw

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@
6666
<li><a href="/admin/">Admin</a></li>
6767
<li><a href="/tasks/">JSON endpoint</a></li>
6868
</ul>
69+
<h3>Quart</h3>
70+
<ul>
71+
<li><a href="/admin/">Admin</a></li>
72+
<li><a href="/docs">Swagger API</a></li>
73+
</ul>
6974
</section>
7075
</div>
7176
{% endblock content %}

0 commit comments

Comments
 (0)