yksa-django-kit/yksa_kit/views.py
2026-08-17 22:50:10 +08:00

97 lines
3 KiB
Python

"""Project-level views every service exposes: health, timezone, legal pages."""
from __future__ import annotations
from functools import lru_cache
from zoneinfo import available_timezones
from django.contrib import messages
from django.db import connection
from django.http import JsonResponse
from django.shortcuts import redirect, render
from django.urls import reverse
from django.utils import timezone
from django.utils.http import url_has_allowed_host_and_scheme
from django.utils.translation import gettext as _
from .context_processors import DEFAULT_COMMON_TIMEZONES
@lru_cache(maxsize=1)
def _timezone_name_options():
try:
names = sorted(available_timezones())
except Exception:
names = list(DEFAULT_COMMON_TIMEZONES)
preferred = ["UTC", "Europe/Moscow", "Asia/Yakutsk"]
ordered = [n for n in preferred if n in names]
ordered += [n for n in names if n not in ordered]
return ordered
def _safe_next_url(request, candidate):
if candidate and url_has_allowed_host_and_scheme(
candidate,
allowed_hosts={request.get_host()},
require_https=request.is_secure(),
):
return candidate
return reverse("timezone-preferences")
def privacy_policy(request):
return render(request, "privacy_policy.html")
def cookie_policy(request):
return render(request, "cookie_policy.html")
def timezone_preferences(request):
timezone_names = _timezone_name_options()
timezone_set = set(timezone_names)
selected_timezone = request.session.get("user_timezone", "UTC")
if selected_timezone not in timezone_set:
selected_timezone = "UTC"
if request.method == "POST":
selected_timezone = (request.POST.get("timezone") or "UTC").strip()
if selected_timezone not in timezone_set:
messages.error(request, _("Selected time zone is not supported."))
else:
request.session["user_timezone"] = selected_timezone
request.session.modified = True
messages.success(request, _("Time zone preference saved."))
return redirect(_safe_next_url(request, request.POST.get("next")))
return render(request, "timezone_preferences.html", {
"timezone_names": timezone_names,
"selected_timezone": selected_timezone,
"next_url": _safe_next_url(
request, request.GET.get("next") or request.META.get("HTTP_REFERER"),
),
})
def health_check(request):
"""Swarm healthcheck target: it must answer without a database, not raise."""
try:
with connection.cursor() as cursor:
cursor.execute("SELECT 1")
return JsonResponse({
"status": "healthy",
"timestamp": timezone.now().isoformat(),
"database": "connected",
})
except Exception as exc:
return JsonResponse(
{
"status": "unhealthy",
"timestamp": timezone.now().isoformat(),
"database": "disconnected",
"error": str(exc),
},
status=503,
)