Add direct-save public content API

This commit is contained in:
2026-09-27 11:40:11 +03:30
parent f6b4ef7dd8
commit 149497d276
6 changed files with 280 additions and 0 deletions

103
apps/content/api/views.py Normal file
View File

@@ -0,0 +1,103 @@
from django.http import HttpResponse
from ninja import Router
from ninja.errors import HttpError
from apps.content.current import AboutContent, HomeContent, ListingContent, SiteContent
from apps.content.api.schemas import AboutPageOut, HomePageOut, ListingPageOut, PageContentOut, SiteContentOut
content_router = Router(tags=["Public content"])
def _media(request, field, alt):
if not field or not field.name:
return None
return {"url": request.build_absolute_uri(field.url), "alt": alt or ""}
def _seo(request, obj):
return {
"title": obj.seo_title,
"description": obj.seo_description,
"image": _media(request, obj.seo_image, obj.seo_image_alt),
}
@content_router.get("/site", response=SiteContentOut)
def get_site_content(request, response: HttpResponse):
site = SiteContent.objects.filter(pk=1).first()
if site is None:
raise HttpError(404, "Site content not found")
response["Cache-Control"] = "no-store"
return {
"official_name": site.official_name,
"short_name": site.short_name,
"faculty_subline": site.faculty_subline,
"description": site.description,
"logo": _media(request, site.logo, site.logo_alt),
"navigation": {
"home": site.nav_home,
"about": site.nav_about,
"events": site.nav_events,
"blog": site.nav_blog,
},
"contacts": {
"email": site.email,
"phone": site.phone,
"telegram": site.telegram_url,
"instagram": site.instagram_url,
"website": site.website_url,
},
"address": site.address,
"footer_copy": site.footer_copy,
"seo": _seo(request, site),
}
@content_router.get("/pages/{slug}", response=PageContentOut)
def get_page_content(request, response: HttpResponse, slug: str):
response["Cache-Control"] = "no-store"
if slug == "home":
page = HomeContent.objects.filter(pk=1).first()
if page is None:
raise HttpError(404, "Page content not found")
return {
"slug": "home", "title": page.title, "intro": page.intro, "seo": _seo(request, page),
"hero_heading": page.hero_heading, "hero_body": page.hero_body,
"hero_image": _media(request, page.hero_image, page.hero_image_alt),
"hero_action_label": page.hero_action_label,
"featured_events_heading": page.featured_events_heading,
"featured_events_intro": page.featured_events_intro,
"featured_events_link_label": page.featured_events_link_label,
"featured_posts_heading": page.featured_posts_heading,
"featured_posts_intro": page.featured_posts_intro,
"featured_posts_link_label": page.featured_posts_link_label,
"participation_heading": page.participation_heading,
"participation_body": page.participation_body,
"participation_image": _media(request, page.participation_image, page.participation_image_alt),
"participation_action_label": page.participation_action_label,
}
if slug == "about":
page = AboutContent.objects.filter(pk=1).first()
if page is None:
raise HttpError(404, "Page content not found")
return {
"slug": "about", "title": page.title, "intro": page.intro, "seo": _seo(request, page),
"identity_heading": page.identity_heading, "identity_body": page.identity_body,
"mission_heading": page.mission_heading, "mission_body": page.mission_body,
"activities_heading": page.activities_heading, "activities_body": page.activities_body,
"values_heading": page.values_heading, "values_body": page.values_body,
"committees_heading": page.committees_heading, "committees_body": page.committees_body,
"affiliations_heading": page.affiliations_heading, "affiliations_body": page.affiliations_body,
"faq_heading": page.faq_heading, "contact_heading": page.contact_heading,
"items": list(page.items.values("kind", "title", "text", "position")),
}
if slug in ("events", "blog"):
page = ListingContent.objects.filter(slug=slug).first()
if page is None:
raise HttpError(404, "Page content not found")
return {"slug": page.slug, "title": page.title, "intro": page.intro, "seo": _seo(request, page)}
raise HttpError(404, "Page content not found")