special galleries: helper module, renderers, templates & urls; hide back in special views; highlight active special

This commit is contained in:
2026-03-27 20:09:35 -04:00
parent 24c1c96f19
commit 532690a329
8 changed files with 252 additions and 64 deletions

71
viewer/specials.py Normal file
View File

@@ -0,0 +1,71 @@
"""
Helpers for assembling "special" galleries (favorites, most-visited, recent).
These functions return filesystem Path objects suitable for use by the
existing directory and image renderers.
"""
from pathlib import Path
from django.conf import settings
from .models import Image as ImModel
SPECIALS = {
"favorites": "Favorites",
"most-visited": "Most Visited",
"recent": "Recent",
}
def special_name(key):
return SPECIALS.get(key, key)
def special_root_url(key, query_dict=None):
# Build a URL for the special gallery root (e.g. /gallery/favorites/)
base = f"/gallery/{key}/"
if not query_dict:
return base
from urllib.parse import urlencode
return base + "?" + urlencode(query_dict)
def get_special_paths(user, key, limit=100):
"""Return a list of pathlib.Path objects for the requested special gallery.
Only include files that actually exist on disk. The returned list is
ordered according to the special gallery semantics.
"""
qs = ImModel.objects.filter(user=user)
if key == "favorites":
qs = qs.filter(favorite=True).order_by("-last_visited")
elif key == "most-visited":
qs = qs.order_by("-visits")
elif key == "recent":
qs = qs.order_by("-last_visited")
else:
return []
if key in ("most-visited", "recent"):
qs = qs[:limit]
paths = []
for row in qs:
try:
p = Path(row.path)
# ensure the stored path is inside GALLERY_ROOT for safety
try:
p.relative_to(settings.GALLERY_ROOT)
except Exception:
# skip paths outside the gallery root
continue
if p.exists() and p.is_file():
paths.append(p)
except Exception:
continue
return paths