Optimize templates & clean code

This commit is contained in:
Nyymix 2025-04-26 20:39:57 +03:00
parent 0c1c888547
commit 86d9ca5066
11 changed files with 98 additions and 48 deletions

View file

@ -61,6 +61,7 @@ class LocationAdmin(admin.ModelAdmin):
search_fields = ('place', 'city__name') search_fields = ('place', 'city__name')
list_per_page = 30 list_per_page = 30
class AlbumAdmin(admin.ModelAdmin): class AlbumAdmin(admin.ModelAdmin):
prepopulated_fields = {'slug': ('name',)} prepopulated_fields = {'slug': ('name',)}
list_display = ('name', 'location', 'album_date', 'is_public', 'upload_link', 'thumbnail') list_display = ('name', 'location', 'album_date', 'is_public', 'upload_link', 'thumbnail')
@ -145,4 +146,4 @@ admin.site.register(City, CityAdmin)
admin.site.register(Location, LocationAdmin) admin.site.register(Location, LocationAdmin)
admin.site.register(Album, AlbumAdmin) admin.site.register(Album, AlbumAdmin)
admin.site.register(Photo, PhotoAdmin) admin.site.register(Photo, PhotoAdmin)
admin.site.register(Redir, RedirAdmin) admin.site.register(Redir, RedirAdmin)

View file

@ -13,9 +13,8 @@ def site_config(request):
try: try:
with open(config_path, 'r') as f: with open(config_path, 'r') as f:
config = json.load(f) config = json.load(f)
cache.set('site_config', config, 3600) cache.set('site_config', config, 3600)
except FileNotFoundError: except FileNotFoundError:
config = {} config = {}
return {'site_config': config} return {'site_config': config}

View file

@ -65,4 +65,4 @@ class Album(models.Model):
@receiver(post_save, sender=Album) @receiver(post_save, sender=Album)
def delete_album_cover_cache(sender, instance, **kwargs): def delete_album_cover_cache(sender, instance, **kwargs):
cache.delete(f'cover_image_data_{instance.pk}') cache.delete(f'photo_md_image_data_{instance.pk}')

View file

@ -20,7 +20,6 @@ class Location(models.Model):
unique_together = ('place', "city") unique_together = ('place', "city")
ordering = ['city'] ordering = ['city']
def __str__(self): def __str__(self):
if self.place: if self.place:
return '{0}, {1}'.format(self.city, self.place) return '{0}, {1}'.format(self.city, self.place)

View file

@ -38,10 +38,10 @@ class Photo(models.Model):
@property @property
def orientation(self): def orientation(self):
return "Portrait" if self.height > self.width else "Landscape" return "Portrait" if self.height > self.width else "Landscape"
@property @property
def aspect_ratio(self): def aspect_ratio(self):
return self.width / self.height return self.width / self.height
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if not self.slug: if not self.slug:
@ -59,7 +59,7 @@ class Photo(models.Model):
def get_next(self): def get_next(self):
return self.__class__.objects.filter(taken_at__gt=self.taken_at, album=self.album).order_by('taken_at').first() return self.__class__.objects.filter(taken_at__gt=self.taken_at, album=self.album).order_by('taken_at').first()
def get_prev(self): def get_prev(self):
return self.__class__.objects.filter(taken_at__lt=self.taken_at, album=self.album).order_by('-taken_at').first() return self.__class__.objects.filter(taken_at__lt=self.taken_at, album=self.album).order_by('-taken_at').first()
@ -77,7 +77,6 @@ class Photo(models.Model):
def __str__(self): def __str__(self):
return f'{self.slug} ({self.orientation}) {self.is_favorite}' return f'{self.slug} ({self.orientation}) {self.is_favorite}'
@receiver(post_save, sender=Photo) @receiver(post_save, sender=Photo)
@ -95,4 +94,4 @@ def handle_photo_creation(sender, instance, created, **kwargs):
# Aseta cover, jos albumilla ei ole vielä sellaista # Aseta cover, jos albumilla ei ole vielä sellaista
if instance.album and not instance.album.cover: if instance.album and not instance.album.cover:
instance.album.cover = instance instance.album.cover = instance
instance.album.save(update_fields=['cover']) instance.album.save(update_fields=['cover'])

View file

@ -15,4 +15,4 @@ class AlbumSitemap(Sitemap):
return obj.album_date return obj.album_date
def location(self, obj): def location(self, obj):
return reverse('gallery:album_url', kwargs={'album_slug': obj.slug}) return reverse('gallery:album_url', kwargs={'album_slug': obj.slug})

View file

@ -30,15 +30,19 @@
<!-- Album cover image --> <!-- Album cover image -->
<div class="uk-card-media-top"> <div class="uk-card-media-top">
<a href="{{ album.get_absolute_url }}"> <a href="{{ album.get_absolute_url }}">
{% with album|cover_image_data as img %} {% with album.cover|photo_image_data as img %}
<img <div class="{% if img.is_placeholder %}uk-blur{% endif %}">
src="{{ img.url }}" <img
width="{{ img.width }}" src="{{ img.url }}"
height="{{ img.height }}" width="{{ img.width }}"
style="aspect-ratio: {{ img.aspect_ratio }};" height="{{ img.height }}"
alt="Cover image for {{ album.name }}" style="aspect-ratio: {{ img.aspect_ratio }};"
title="{{ album.name }}" alt="Cover image for {{ album.name }}"
loading="lazy"> title="{{ album.name }}"
loading="lazy"
decoding="async"
onload="this.parentElement.classList.remove('uk-blur'); this.classList.add('fade-in');">
</div>
{% endwith %} {% endwith %}
</a> </a>
</div> </div>

View file

@ -31,15 +31,19 @@
<!-- Album cover image --> <!-- Album cover image -->
<div class="uk-card-media-top"> <div class="uk-card-media-top">
<a href="{{ album.get_absolute_url }}"> <a href="{{ album.get_absolute_url }}">
{% with album|cover_image_data as img %} {% with album.cover|photo_image_data as img %}
<img <div class="{% if img.is_placeholder %}uk-blur{% endif %}">
src="{{ img.url }}" <img
width="{{ img.width }}" src="{{ img.url }}"
height="{{ img.height }}" width="{{ img.width }}"
style="aspect-ratio: {{ img.aspect_ratio }};" height="{{ img.height }}"
alt="Cover image for {{ album.name }}" style="aspect-ratio: {{ img.aspect_ratio }};"
title="{{ album.name }}" alt="Cover image for {{ album.name }}"
loading="lazy"> title="{{ album.name }}"
loading="lazy"
decoding="async"
onload="this.parentElement.classList.remove('uk-blur'); this.classList.add('fade-in');">
</div>
{% endwith %} {% endwith %}
</a> </a>
</div> </div>

View file

@ -15,6 +15,7 @@
<!-- Favorite random portrait photos --> <!-- Favorite random portrait photos -->
{% load top_tags %} {% load top_tags %}
{% load image_tags %}
{% random_favorite_photos_portrait 10 as top_portrait_photos %} {% random_favorite_photos_portrait 10 as top_portrait_photos %}
{% if top_portrait_photos %} {% if top_portrait_photos %}
@ -22,11 +23,13 @@
<div class="uk-position-relative uk-visible-toggle uk-light" tabindex="-1"> <div class="uk-position-relative uk-visible-toggle uk-light" tabindex="-1">
<div class="uk-slider-items uk-child-width-1-2 uk-child-width-1-3@s uk-child-width-1-4@m"> <div class="uk-slider-items uk-child-width-1-2 uk-child-width-1-3@s uk-child-width-1-4@m">
{% for photo in top_portrait_photos %} {% for photo in top_portrait_photos %}
{% with photo|photo_image_data as data %}
<div> <div>
<a href="{{ photo.get_absolute_url }}"> <a href="{{ photo.get_absolute_url }}">
<img src="{{ photo.photo_md.url }}" alt="{{ photo.album.slug }}" width="400" height="600" style="object-fit: cover;"> <img src="{{ data.url }}" alt="{{ photo.album.slug }}" width="{{ data.width }}" height="{{ data.height }}" style="object-fit: cover;" loading="lazy">
</a> </a>
</div> </div>
{% endwith %}
{% endfor %} {% endfor %}
</div> </div>
<a class="uk-position-center-left uk-position-small uk-hidden-hover" href uk-slidenav-previous uk-slider-item="previous"></a> <a class="uk-position-center-left uk-position-small uk-hidden-hover" href uk-slidenav-previous uk-slider-item="previous"></a>
@ -46,15 +49,19 @@
<!-- Album cover image --> <!-- Album cover image -->
<div class="uk-card-media-top"> <div class="uk-card-media-top">
<a href="{{ album.get_absolute_url }}"> <a href="{{ album.get_absolute_url }}">
{% with album|cover_image_data as img %} {% with album.cover|photo_image_data as img %}
<img <div class="{% if img.is_placeholder %}uk-blur{% endif %}">
src="{{ img.url }}" <img
width="{{ img.width }}" src="{{ img.url }}"
height="{{ img.height }}" width="{{ img.width }}"
style="aspect-ratio: {{ img.aspect_ratio }};" height="{{ img.height }}"
alt="Cover image for {{ album.name }}" style="aspect-ratio: {{ img.aspect_ratio }};"
title="{{ album.name }}" alt="Cover image for {{ album.name }}"
loading="lazy"> title="{{ album.name }}"
loading="lazy"
decoding="async"
onload="this.parentElement.classList.remove('uk-blur'); this.classList.add('fade-in');">
</div>
{% endwith %} {% endwith %}
</a> </a>
</div> </div>

View file

@ -6,24 +6,36 @@ from django.templatetags.static import static
register = template.Library() register = template.Library()
@register.filter
def cover_image_data(album):
cache_key = f'cover_image_data_{album.pk}' @register.filter
def photo_image_data(photo):
"""
Generate resized image data for Photo objects.
"""
if not photo:
return {
"url": static("img/placeholder.png"),
"width": 1200,
"height": 800,
"aspect_ratio": round(1200 / 800, 3),
"is_placeholder": True,
}
cache_key = f'photo_md_image_data_{photo.pk}'
data = cache.get(cache_key) data = cache.get(cache_key)
if data: if data:
return data return data
photo = getattr(album, "cover", None)
max_w, max_h = 720, 720 max_w, max_h = 720, 720
if not photo or not photo.width or not photo.height: if not photo.width or not photo.height:
data = { data = {
"url": static("img/placeholder.png"), "url": static("img/placeholder.png"),
"width": 1200, "width": 1200,
"height": 800, "height": 800,
"aspect_ratio": round(1200 / 800, 3), "aspect_ratio": round(1200 / 800, 3),
"is_placeholder": True,
} }
else: else:
aspect = photo.aspect_ratio aspect = photo.aspect_ratio
@ -39,7 +51,8 @@ def cover_image_data(album):
"width": w, "width": w,
"height": h, "height": h,
"aspect_ratio": round(aspect, 3), "aspect_ratio": round(aspect, 3),
"is_placeholder": False,
} }
cache.set(cache_key, data, 60 * 60 * 24) cache.set(cache_key, data, 60 * 60 * 24)
return data return data

View file

@ -1,8 +1,10 @@
body { body {
font: 400 14px/20px "Helvetica Neue",Helvetica,Arial,sans-serif; font: 400 14px/20px "Helvetica Neue", Helvetica, Arial, sans-serif;
} }
.uk-navbar-item, .uk-navbar-nav>li>a, .uk-navbar-toggle { .uk-navbar-item,
.uk-navbar-nav>li>a,
.uk-navbar-toggle {
min-height: 50px; min-height: 50px;
} }
@ -12,5 +14,27 @@ body {
} }
.uk-breadcrumb>:nth-child(n+2):not(.uk-first-column)::before { .uk-breadcrumb>:nth-child(n+2):not(.uk-first-column)::before {
margin: 0 10px 0 calc(10px - 4px); margin: 0 10px 0 calc(10px - 4px);
}
.uk-blur img {
filter: blur(8px);
transform: scale(1.05);
transition: filter 0.5s ease, transform 0.5s ease;
}
.fade-in {
animation: fadeIn 0.8s ease forwards;
}
@keyframes fadeIn {
0% {
opacity: 0;
transform: scale(1.02);
}
100% {
opacity: 1;
transform: scale(1);
}
} }