Auto-mount defpages: eliminate Python route stubs across all 9 services
Some checks failed
Build and Deploy / build-and-deploy (push) Failing after 16s
Some checks failed
Build and Deploy / build-and-deploy (push) Failing after 16s
Defpages are now declared with absolute paths in .sx files and auto-mounted directly on the Quart app, removing ~850 lines of blueprint mount_pages calls, before_request hooks, and g.* wrapper boilerplate. A new page = one defpage declaration, nothing else. Infrastructure: - async_eval awaits coroutine results from callable dispatch - auto_mount_pages() mounts all registered defpages on the app - g._defpage_ctx pattern passes helper data to layout context Migrated: sx, account, orders, federation, cart, market, events, blog Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,15 +8,12 @@ from __future__ import annotations
|
||||
from quart import (
|
||||
Blueprint,
|
||||
request,
|
||||
redirect,
|
||||
g,
|
||||
)
|
||||
from sqlalchemy import select
|
||||
|
||||
from shared.models import UserNewsletter
|
||||
from shared.models.ghost_membership_entities import GhostNewsletter
|
||||
from shared.infrastructure.urls import login_url
|
||||
from shared.infrastructure.fragments import fetch_fragment, fetch_fragments
|
||||
from shared.infrastructure.fragments import fetch_fragments
|
||||
from shared.sx.helpers import sx_response
|
||||
|
||||
|
||||
@@ -25,8 +22,7 @@ def register(url_prefix="/"):
|
||||
|
||||
@account_bp.before_request
|
||||
async def _prepare_page_data():
|
||||
"""Fetch account_nav fragments and load data for defpage routes."""
|
||||
# Fetch account nav items for layout (was in context_processor)
|
||||
"""Fetch account_nav fragments for layout."""
|
||||
events_nav, cart_nav, artdag_nav = await fetch_fragments([
|
||||
("events", "account-nav-item", {}),
|
||||
("cart", "account-nav-item", {}),
|
||||
@@ -34,48 +30,6 @@ def register(url_prefix="/"):
|
||||
], required=False)
|
||||
g.account_nav = events_nav + cart_nav + artdag_nav
|
||||
|
||||
if request.method != "GET":
|
||||
return
|
||||
|
||||
endpoint = request.endpoint or ""
|
||||
|
||||
# Newsletters page — load newsletter data
|
||||
if endpoint.endswith("defpage_newsletters"):
|
||||
result = await g.s.execute(
|
||||
select(GhostNewsletter).order_by(GhostNewsletter.name)
|
||||
)
|
||||
all_newsletters = result.scalars().all()
|
||||
|
||||
sub_result = await g.s.execute(
|
||||
select(UserNewsletter).where(
|
||||
UserNewsletter.user_id == g.user.id,
|
||||
)
|
||||
)
|
||||
user_subs = {un.newsletter_id: un for un in sub_result.scalars().all()}
|
||||
|
||||
newsletter_list = []
|
||||
for nl in all_newsletters:
|
||||
un = user_subs.get(nl.id)
|
||||
newsletter_list.append({
|
||||
"newsletter": nl,
|
||||
"un": un,
|
||||
"subscribed": un.subscribed if un else False,
|
||||
})
|
||||
g.newsletters_data = newsletter_list
|
||||
|
||||
# Fragment page — load fragment from events service
|
||||
elif endpoint.endswith("defpage_fragment_page"):
|
||||
slug = request.view_args.get("slug")
|
||||
if slug and g.get("user"):
|
||||
fragment_html = await fetch_fragment(
|
||||
"events", "account-page",
|
||||
params={"slug": slug, "user_id": str(g.user.id)},
|
||||
)
|
||||
if not fragment_html:
|
||||
from quart import abort
|
||||
abort(404)
|
||||
g.fragment_page_data = fragment_html
|
||||
|
||||
@account_bp.post("/newsletter/<int:newsletter_id>/toggle/")
|
||||
async def toggle_newsletter(newsletter_id: int):
|
||||
if not g.get("user"):
|
||||
|
||||
Reference in New Issue
Block a user