Skip to content

Commit

Permalink
add Quart asgi template (#1138)
Browse files Browse the repository at this point in the history
  • Loading branch information
sinisaos authored Jan 17, 2025
1 parent 965c5b3 commit 02ef5f5
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ Let Piccolo scaffold you an ASGI web app, using Piccolo as the ORM:
piccolo asgi new
```

[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.
[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.

## Are you a Django user?

Expand Down
1 change: 1 addition & 0 deletions piccolo/apps/asgi/commands/new.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"litestar": ["litestar"],
"esmerald": ["esmerald"],
"lilya": ["lilya"],
"quart": ["quart", "quart_schema"],
}
ROUTERS = list(ROUTER_DEPENDENCIES.keys())

Expand Down
119 changes: 119 additions & 0 deletions piccolo/apps/asgi/commands/templates/app/_quart_app.py.jinja
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import typing as t
from http import HTTPStatus

from hypercorn.middleware import DispatcherMiddleware
from piccolo.engine import engine_finder
from piccolo_admin.endpoints import create_admin
from piccolo_api.crud.serializers import create_pydantic_model
from quart import Quart
from quart_schema import (
Info,
QuartSchema,
hide,
tag,
validate_request,
validate_response,
)

from home.endpoints import index
from home.piccolo_app import APP_CONFIG
from home.tables import Task


app = Quart(__name__, static_folder="static")
QuartSchema(app, info=Info(title="Quart API", version="0.1.0"))


TaskModelIn: t.Any = create_pydantic_model(
table=Task,
model_name="TaskModelIn",
)
TaskModelOut: t.Any = create_pydantic_model(
table=Task,
include_default_columns=True,
model_name="TaskModelOut",
)


@app.get("/")
@hide
def home():
return index()


@app.get("/tasks/")
@validate_response(t.List[TaskModelOut])
@tag(["Task"])
async def tasks():
return await Task.select().order_by(Task._meta.primary_key, ascending=False)


@app.post("/tasks/")
@validate_request(TaskModelIn)
@validate_response(TaskModelOut)
@tag(["Task"])
async def create_task(data: TaskModelIn):
task = Task(**data.model_dump())
await task.save()
return task.to_dict(), HTTPStatus.CREATED


@app.put("/tasks/<int:task_id>/")
@validate_request(TaskModelIn)
@validate_response(TaskModelOut)
@tag(["Task"])
async def update_task(task_id: int, data: TaskModelIn):
task = await Task.objects().get(Task._meta.primary_key == task_id)
if not task:
return {}, HTTPStatus.NOT_FOUND

for key, value in data.model_dump().items():
setattr(task, key, value)

await task.save()

return task.to_dict(), HTTPStatus.OK


@app.delete("/tasks/<int:task_id>/")
@validate_response(TaskModelOut)
@tag(["Task"])
async def delete_task(task_id: int):
task = await Task.objects().get(Task._meta.primary_key == task_id)
if not task:
return {}, HTTPStatus.NOT_FOUND

await task.remove()

return {}, HTTPStatus.OK


@app.before_serving
async def open_database_connection_pool():
try:
engine = engine_finder()
await engine.start_connection_pool()
except Exception:
print("Unable to connect to the database")


@app.after_serving
async def close_database_connection_pool():
try:
engine = engine_finder()
await engine.close_connection_pool()
except Exception:
print("Unable to connect to the database")


# enable the admin application using DispatcherMiddleware
app = DispatcherMiddleware( # type: ignore
{
"/admin": create_admin(
tables=APP_CONFIG.table_classes,
# Required when running under HTTPS:
# allowed_hosts=['my_site.com']
),
"": app,
}
)
2 changes: 2 additions & 0 deletions piccolo/apps/asgi/commands/templates/app/app.py.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@
{% include '_esmerald_app.py.jinja' %}
{% elif router == 'lilya' %}
{% include '_lilya_app.py.jinja' %}
{% elif router == 'quart' %}
{% include '_quart_app.py.jinja' %}
{% endif %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import os

import jinja2

from quart import Response

ENVIRONMENT = jinja2.Environment(
loader=jinja2.FileSystemLoader(
searchpath=os.path.join(os.path.dirname(__file__), "templates")
)
)


def index():
template = ENVIRONMENT.get_template("home.html.jinja")
content = template.render(title="Piccolo + ASGI")
return Response(content)

Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@
{% include '_esmerald_endpoints.py.jinja' %}
{% elif router == 'lilya' %}
{% include '_lilya_endpoints.py.jinja' %}
{% elif router == 'quart' %}
{% include '_quart_endpoints.py.jinja' %}
{% endif %}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@
<li><a href="/admin/">Admin</a></li>
<li><a href="/tasks/">JSON endpoint</a></li>
</ul>
<h3>Quart</h3>
<ul>
<li><a href="/admin/">Admin</a></li>
<li><a href="/docs">Swagger API</a></li>
</ul>
</section>
</div>
{% endblock content %}

0 comments on commit 02ef5f5

Please sign in to comment.