use database
parent
6e0023497c
commit
ca762f41c9
|
@ -20,9 +20,11 @@ package_dir =
|
|||
packages = find:
|
||||
python_requires = >=3.10
|
||||
install_requires =
|
||||
aiosqlite
|
||||
jinja2
|
||||
python-multipart
|
||||
starlette
|
||||
tortoise-orm
|
||||
uvicorn[standard]
|
||||
|
||||
[options.packages.find]
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
from uuid import UUID, uuid4
|
||||
|
||||
from jinja2 import PackageLoader
|
||||
from starlette.applications import Starlette
|
||||
from starlette.requests import Request
|
||||
|
@ -7,19 +5,32 @@ from starlette.responses import Response
|
|||
from starlette.routing import Route, Mount
|
||||
from starlette.staticfiles import StaticFiles
|
||||
from starlette.templating import Jinja2Templates
|
||||
from uvicorn import run
|
||||
from tortoise import fields, Tortoise
|
||||
from tortoise.models import Model
|
||||
from uvicorn import Config, Server
|
||||
from uvloop import run
|
||||
|
||||
|
||||
class Note(Model):
|
||||
id = fields.UUIDField(pk=True)
|
||||
paragraphs: fields.ReverseRelation["Paragraph"]
|
||||
|
||||
|
||||
class Paragraph(Model):
|
||||
id = fields.UUIDField(pk=True)
|
||||
note: fields.ForeignKeyRelation[Note] = fields.ForeignKeyField(
|
||||
"model.Note", related_name="paragraphs"
|
||||
)
|
||||
content = fields.TextField(default="")
|
||||
|
||||
|
||||
templates = Jinja2Templates(
|
||||
directory="/nonexistent", # just a dummy, FileSystemLoader is not used
|
||||
loader=PackageLoader("wikinotes"),
|
||||
)
|
||||
notes: dict[UUID, list[UUID]] = {}
|
||||
paragraphs: dict[UUID, str] = {}
|
||||
|
||||
|
||||
async def home(request: Request) -> Response:
|
||||
only_body = request.headers.get("hx-request", "false") == "true"
|
||||
return templates.TemplateResponse(
|
||||
"home.html",
|
||||
headers={
|
||||
|
@ -27,89 +38,79 @@ async def home(request: Request) -> Response:
|
|||
},
|
||||
context={
|
||||
"request": request,
|
||||
"only_body": only_body,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
async def create_note(request: Request) -> Response:
|
||||
note_id = uuid4()
|
||||
notes[note_id] = []
|
||||
note = await Note.create()
|
||||
await note.fetch_related("paragraphs")
|
||||
return templates.TemplateResponse(
|
||||
"note.html",
|
||||
headers={
|
||||
"HX-Push-Url": str(request.url_for("note", note_id=note_id)),
|
||||
"HX-Push-Url": str(request.url_for("note", note_id=note.id)),
|
||||
},
|
||||
context={
|
||||
"request": request,
|
||||
"only_body": True,
|
||||
"note_id": note_id,
|
||||
"paragraphs": [],
|
||||
"note": note,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
async def note(request: Request) -> Response:
|
||||
note_id = request.path_params["note_id"]
|
||||
only_body = request.headers.get("hx-request", "false") == "true"
|
||||
note = await Note.get(id=request.path_params["note_id"])
|
||||
await note.fetch_related("paragraphs")
|
||||
return templates.TemplateResponse(
|
||||
"note.html",
|
||||
headers={
|
||||
"HX-Push-Url": str(request.url_for("note", note_id=note_id)),
|
||||
"HX-Push-Url": str(request.url_for("note", note_id=note.id)),
|
||||
},
|
||||
context={
|
||||
"request": request,
|
||||
"only_body": only_body,
|
||||
"note_id": note_id,
|
||||
"paragraphs": [(id, paragraphs[id]) for id in notes[note_id]],
|
||||
"note": note,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
async def create_paragraph(request: Request) -> Response:
|
||||
note_id = request.path_params["note_id"]
|
||||
paragraph_id = uuid4()
|
||||
note = await Note.get(id=request.path_params["note_id"])
|
||||
async with request.form() as form:
|
||||
paragraphs[paragraph_id] = str(form["content"])
|
||||
notes[note_id] = [paragraph_id]
|
||||
paragraph = await Paragraph.create(note=note, content=str(form["content"]))
|
||||
return templates.TemplateResponse(
|
||||
"paragraph.html",
|
||||
context={
|
||||
"request": request,
|
||||
"note_id": note_id,
|
||||
"paragraph_id": paragraph_id,
|
||||
"content": paragraphs[paragraph_id],
|
||||
"note": note,
|
||||
"paragraph": paragraph,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
async def paragraph(request: Request) -> Response:
|
||||
note_id = request.path_params["note_id"]
|
||||
paragraph_id = request.path_params["paragraph_id"]
|
||||
note = await Note.get(id=request.path_params["note_id"])
|
||||
paragraph = await Paragraph.get(id=request.path_params["paragraph_id"])
|
||||
if request.method == "PUT":
|
||||
async with request.form() as form:
|
||||
paragraphs[paragraph_id] = str(form["content"])
|
||||
await paragraph.update_from_dict({"content": str(form["content"])}).save()
|
||||
return templates.TemplateResponse(
|
||||
"paragraph.html",
|
||||
context={
|
||||
"request": request,
|
||||
"note_id": note_id,
|
||||
"paragraph_id": paragraph_id,
|
||||
"content": paragraphs[paragraph_id],
|
||||
"note": note,
|
||||
"paragraph": paragraph,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
async def edit_paragraph(request: Request) -> Response:
|
||||
note_id = request.path_params["note_id"]
|
||||
paragraph_id = request.path_params["paragraph_id"]
|
||||
note = await Note.get(id=request.path_params["note_id"])
|
||||
paragraph = await Paragraph.get(id=request.path_params["paragraph_id"])
|
||||
return templates.TemplateResponse(
|
||||
"edit.html",
|
||||
context={
|
||||
"request": request,
|
||||
"note_id": note_id,
|
||||
"paragraph_id": paragraph_id,
|
||||
"content": paragraphs[paragraph_id],
|
||||
"note": note,
|
||||
"paragraph": paragraph,
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -147,5 +148,16 @@ app = Starlette(
|
|||
)
|
||||
|
||||
|
||||
async def async_main() -> None:
|
||||
await Tortoise.init(db_url="sqlite://:memory:", modules={"model": ["wikinotes"]})
|
||||
await Tortoise.generate_schemas()
|
||||
|
||||
config = Config("wikinotes:app", port=8080, log_level="info")
|
||||
server = Server(config)
|
||||
await server.serve()
|
||||
|
||||
await Tortoise.close_connections()
|
||||
|
||||
|
||||
def main() -> None:
|
||||
run("wikinotes:app", port=8080, log_level="info")
|
||||
run(async_main())
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% if not only_body %}
|
||||
{% if request.headers.get("hx-request", "false") != "true" %}
|
||||
{% extends "base.html" %}
|
||||
{% endif %}
|
||||
{% block body %}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<form hx-put="{{ url_for("paragraph", note_id=note_id, paragraph_id=paragraph_id) }}" hx-target="this" hx-swap="outerHTML">
|
||||
<textarea class="form-control mb-3" name="content" rows="10" autofocus>{{ content }}</textarea>
|
||||
<form hx-put="{{ url_for("paragraph", note_id=note.id, paragraph_id=paragraph.id) }}" hx-target="this" hx-swap="outerHTML">
|
||||
<textarea class="form-control mb-3" name="content" rows="10" autofocus>{{ paragraph.content }}</textarea>
|
||||
<button class="btn btn-primary">Submit</button>
|
||||
<button class="btn" hx-get="{{ url_for("paragraph", note_id=note_id, paragraph_id=paragraph_id) }}">Cancel</button>
|
||||
<button class="btn" hx-get="{{ url_for("paragraph", note_id=note.id, paragraph_id=paragraph.id) }}">Cancel</button>
|
||||
</form>
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
</div>
|
||||
{% endblock %}
|
||||
{% block main %}
|
||||
{% for paragraph_id, content in paragraphs %}
|
||||
{% for paragraph in note.paragraphs %}
|
||||
{% include "paragraph.html" %}
|
||||
{% else %}
|
||||
<form hx-post="{{ url_for("create_paragraph", note_id=note_id) }}" hx-target="this" hx-swap="outerHTML">
|
||||
<form hx-post="{{ url_for("create_paragraph", note_id=note.id) }}" hx-target="this" hx-swap="outerHTML">
|
||||
<textarea class="form-control mb-3" name="content" rows="10" autofocus></textarea>
|
||||
<button class="btn btn-primary">Submit</button>
|
||||
</form>
|
||||
|
|
|
@ -1 +1 @@
|
|||
<p class="editable" title="Click to edit" hx-get="{{ url_for("edit_paragraph", note_id=note_id, paragraph_id=paragraph_id) }}" hx-target="this" hx-swap="outerHTML">{{ content }}</p>
|
||||
<p class="editable" title="Click to edit" hx-get="{{ url_for("edit_paragraph", note_id=note.id, paragraph_id=paragraph.id) }}" hx-target="this" hx-swap="outerHTML">{{ paragraph.content }}</p>
|
||||
|
|
Loading…
Reference in New Issue