Update and optimize top tags

This commit is contained in:
Nyymix 2025-04-24 23:32:12 +03:00
parent acb528b697
commit 7a419f3b14

View file

@ -1,3 +1,5 @@
import random
from django import template
from django.core.cache import cache
from django.db.models import F
@ -6,19 +8,21 @@ from gallery.models import Album, Photo
register = template.Library()
@register.simple_tag
def last_albums(count=5):
# Returns the latest public albums, cached for 1 hour.
cache_key = f"last_albums_{count}"
albums = cache.get(cache_key)
if albums is None:
albums = Album.objects.filter(is_public=True).order_by("-album_date")[:count]
cache.set(cache_key, albums, timeout=60 * 60) # 1h
cache.set(cache_key, albums, timeout=60 * 60) # 1h
return albums
@register.simple_tag
def top_photos(count=5):
# Returns top photos by is_favorite, likes, and views.
# Uses select_related to reduce DB hits. Cached for 1 hour.
cache_key = f"top_photos_{count}"
photos = cache.get(cache_key)
if photos is None:
@ -28,56 +32,112 @@ def top_photos(count=5):
.order_by('-is_favorite', '-likes', '-views')
.select_related('album')[:count]
)
cache.set(cache_key, albums, timeout=60 * 60) # 1h
# FIXED: previously cached as 'albums' by mistake
cache.set(cache_key, photos, timeout=60 * 60)
return photos
@register.simple_tag
def random_photos_landscape(count=5):
cache_key = f"random_photos_landscape_{count}"
# Returns random landscape-oriented photos from public albums.
# NO CACHING: always random.
all_ids = list(
Photo.objects
.filter(album__is_public=True, width__gt=F('height'))
.values_list('id', flat=True)[:500] # limit ID pool to improve performance
)
selected_ids = random.sample(all_ids, min(count, len(all_ids)))
photos = Photo.objects.filter(id__in=selected_ids)
return photos
@register.simple_tag
def random_favorite_photos_landscape(count=5):
# Returns random landscape-oriented favorite photos from public albums.
# If fewer than 'count' photos are available, returns an empty list.
# Results are cached for 1 hour for performance.
cache_key = f"random_favorite_photos_landscape_{count}"
photos = cache.get(cache_key)
if photos is None:
photos = (
Photo.objects
.filter(album__is_public=True, width__gt=F('height'))
.order_by('?')[:count]
# Get all qualifying photos (landscape, favorite, public)
queryset = Photo.objects.filter(
is_favorite=True,
width__gt=F('height'),
album__is_public=True
)
cache.set(cache_key, photos, timeout=30) # 30 sec
if queryset.count() < count:
return []
# Randomize and take the requested number
photos = queryset.order_by('?')[:count]
cache.set(cache_key, list(photos), timeout=60 * 60)
return photos
@register.simple_tag
def random_favorite_photos_portrait(count=5):
# Returns random portrait-oriented favorite photos from public albums.
# If fewer than 'count' photos are available, returns an empty list.
# Results are cached for 1 hour for performance.
cache_key = f"random_favorite_photos_portrait_{count}"
photos = cache.get(cache_key)
if photos is None:
# Get all qualifying photos (portrait, favorite, public)
queryset = Photo.objects.filter(
is_favorite=True,
height__gt=F('width'),
album__is_public=True
)
if queryset.count() < count:
return []
photos = queryset.order_by('?')[:count]
cache.set(cache_key, list(photos), timeout=60 * 60) # Cache as list, not queryset
return photos
@register.simple_tag
def top_photos_landscape(count=5):
# Returns top landscape-oriented photos sorted by views.
# Uses select_related and is cached for 1 hour.
cache_key = f"top_photos_landscape_{count}"
photos = cache.get(cache_key)
if photos is None:
if photos is None:
photos = (
Photo.objects
.filter(album__is_public=True, width__gt=F('height'))
.order_by('-views')
.select_related('album')[:count]
)
cache.set(cache_key, photos, timeout=60 * 60) # 1h
cache.set(cache_key, photos, timeout=60 * 60)
return photos
@register.simple_tag
def top_photos_portrait(count=5):
# Returns top portrait-oriented photos sorted by views.
# Uses select_related and is cached for 1 hour.
cache_key = f"top_photos_portrait_{count}"
photos = cache.get(cache_key)
if photos is None:
if photos is None:
photos = (
Photo.objects
.filter(album__is_public=True, height__gt=F('width'))
.order_by('-views')
.select_related('album')[:count]
)
cache.set(cache_key, photos, timeout=60 * 60) # 1h
cache.set(cache_key, photos, timeout=60 * 60)
return photos
@register.simple_tag
def top_photos_in_album(album, count=5):
# Returns top photos in a specific album by favorite, likes, and views.
# Cached for 1 hour using album.id as cache key part.
cache_key = f"top_photos_album_{album.id}_{count}"
photos = cache.get(cache_key)
if photos is None:
@ -87,6 +147,5 @@ def top_photos_in_album(album, count=5):
.order_by('-is_favorite', '-likes', '-views')
.select_related('album')[:count]
)
cache.set(cache_key, photos, timeout=60 * 60) # 1h
return photos
cache.set(cache_key, photos, timeout=60 * 60)
return photos