From 0804db3c2b7a30e0b4fdaa0c0e827fda0fae144f Mon Sep 17 00:00:00 2001 From: loki Date: Thu, 6 Nov 2025 03:58:12 +1000 Subject: [PATCH 1/8] basic htmx --- blog/post/views.py | 58 +++++++++++++++------------------ blog/tags/views.py | 21 +++++------- blog/templates/footer.html | 5 +++ blog/templates/icons/icons.htmx | 6 ++++ blog/templates/index.html | 15 +++++++++ blog/templates/layout.html | 22 ++++++++++--- blog/templates/pages.htmx | 8 +++++ blog/templates/post.html | 15 +++++++-- blog/templates/post.htmx | 28 ++++++++++++++++ blog/templates/posts.html | 16 ++++----- blog/templates/posts.htmx | 27 +++++++++++++++ blog/templates/tags.htmx | 10 ++++++ 12 files changed, 170 insertions(+), 61 deletions(-) create mode 100644 blog/templates/icons/icons.htmx create mode 100644 blog/templates/index.html create mode 100644 blog/templates/pages.htmx create mode 100644 blog/templates/post.htmx create mode 100644 blog/templates/posts.htmx create mode 100644 blog/templates/tags.htmx diff --git a/blog/post/views.py b/blog/post/views.py index a0603a2..1447d1f 100644 --- a/blog/post/views.py +++ b/blog/post/views.py @@ -1,8 +1,6 @@ import datetime from typing import cast, ParamSpec, TypeVar -from functools import wraps -from collections.abc import Callable import markdown from flask import ( Blueprint, @@ -13,6 +11,7 @@ render_template, request, url_for, + abort, ) @@ -26,48 +25,47 @@ R = TypeVar("R") -def pages_gen( - f: Callable[P, R], -) -> Callable[P, R]: - @wraps(f) - def decorated_function(*args: P.args, **kwargs: P.kwargs) -> R: - page_category = cast("list[int]", current_app.config["PAGE_CATEGORY"]) - - post_service = ServiceFactory.create_post_service() - pages = post_service.get_page_posts(page_category) - - icon_service = ServiceFactory.create_icon_service() - icons = icon_service.get_all_icons() - kwargs["icons"] = icons - kwargs["pages"] = pages - return f(*args, **kwargs) - - return decorated_function - - @post.route("/") @cache.cached(timeout=50) # pyright: ignore[reportUntypedFunctionDecorator] -@pages_gen def index(**kwargs: str) -> Response | str: + return render_template("index.html", **kwargs) + + +@post.route("/posts") +@cache.cached(timeout=50) # pyright: ignore[reportUntypedFunctionDecorator] +def posts(**kwargs: str) -> Response | str: post_service = ServiceFactory.create_post_service() posts = post_service.get_published_posts() return render_template("posts.html", posts=posts, **kwargs) +@post.route("/hx/pages") +@cache.cached(timeout=50) # pyright: ignore[reportUntypedFunctionDecorator] +def pages_hx() -> Response | str: + page_category = cast("list[int]", current_app.config["PAGE_CATEGORY"]) + post_service = ServiceFactory.create_post_service() + pages = post_service.get_page_posts(page_category) + return render_template("pages.htmx", pages=pages) + + +@post.route("/hx/icons") +@cache.cached(timeout=50) # pyright: ignore[reportUntypedFunctionDecorator] +def icons_hx() -> Response | str: + icon_service = ServiceFactory.create_icon_service() + icons = icon_service.get_all_icons() + return render_template("icons/icons.htmx", icons=icons) + + @post.route("/") @cache.cached(timeout=50) # pyright: ignore[reportUntypedFunctionDecorator] -@pages_gen def view(alias: str | None = None, **kwargs: str) -> Response | str: + template = "post.htmx" if request.args.get("hx") else "post.html" if alias is None: - from flask import abort - abort(404) post_service = ServiceFactory.create_post_service() post = post_service.get_post_by_alias(alias) if not post: - from flask import abort - abort(404) # For page categories, we need to check if it's a page or a regular post @@ -76,8 +74,6 @@ def view(alias: str | None = None, **kwargs: str) -> Response | str: is_published = post.publishedon is not None if not (is_published or is_page): - from flask import abort - abort(404) # Get tags for the post @@ -89,8 +85,8 @@ def view(alias: str | None = None, **kwargs: str) -> Response | str: page_category_obj = category_service.get_category_by_id(post.category_id) if page_category_obj and page_category_obj.template: - return render_template("post.html", post=post, tags=tags, **kwargs) - return render_template("post.html", post=post, tags=tags, **kwargs) + return render_template(template, post=post, tags=tags, **kwargs) + return render_template(template, post=post, tags=tags, **kwargs) @flask_sitemap.register_generator diff --git a/blog/tags/views.py b/blog/tags/views.py index 05e37ab..68011fb 100644 --- a/blog/tags/views.py +++ b/blog/tags/views.py @@ -1,8 +1,7 @@ -from typing import TYPE_CHECKING, ParamSpecKwargs +from typing import TYPE_CHECKING -from flask import Blueprint, render_template, Response +from flask import Blueprint, render_template, Response, abort, request -from blog.post.views import pages_gen from blog.services.factory import ServiceFactory if TYPE_CHECKING: @@ -12,29 +11,25 @@ @tags.route("/") -@pages_gen -def index(**kwargs: ParamSpecKwargs) -> Response | str: +def index() -> Response | str: + template = "tags.htmx" if request.args.get("hx") else "tags.html" tag_service = ServiceFactory.create_tag_service() tags = tag_service.get_all_tags() - return render_template("tags.html", tags=tags, **kwargs) + return render_template(template, tags=tags) @tags.route("/") -@pages_gen -def view(alias: str | None = None, **kwargs: ParamSpecKwargs) -> Response | str: +def view(alias: str | None = None) -> Response | str: + template = "index.html" if request.args.get("hx") else "post.htmx" if alias is None: - from flask import abort - abort(404) tag_service = ServiceFactory.create_tag_service() tag = tag_service.get_tag_by_alias(alias) if not tag: - from flask import abort - abort(404) # Get posts for this tag through the post service post_service = ServiceFactory.create_post_service() posts = post_service.get_posts_by_tag(tag.id) if tag.id else [] - return render_template("posts.html", posts=posts, tag=tag, **kwargs) + return render_template(template, posts=posts, tag=tag) diff --git a/blog/templates/footer.html b/blog/templates/footer.html index 3d12c40..1f22867 100644 --- a/blog/templates/footer.html +++ b/blog/templates/footer.html @@ -1,6 +1,11 @@