diff --git a/gallery/models/photo.py b/gallery/models/photo.py index 112e008..ae8654a 100644 --- a/gallery/models/photo.py +++ b/gallery/models/photo.py @@ -1,4 +1,5 @@ import os +import random from datetime import datetime from django.db import models @@ -11,13 +12,12 @@ from gallery.models import Album def get_upload_path(instance, filename): - """Määrittää lopullisen tallennuspolun heti kuvan tallennusvaiheessa.""" return os.path.join('albums', str(instance.album.slug), filename) class Photo(models.Model): album = models.ForeignKey(Album, on_delete=models.CASCADE, related_name='photos', verbose_name="Album") - slug = models.CharField(max_length=15, editable=False, verbose_name="Photo Slug") + slug = models.CharField(unique=True, max_length=15, editable=False, verbose_name="Photo Slug") photo = models.ImageField(upload_to=get_upload_path, height_field='height', width_field='width', verbose_name="Photo") # Thumbnail-versiot @@ -36,44 +36,56 @@ class Photo(models.Model): @property def orientation(self): return "Portrait" if self.height > self.width else "Landscape" + + @property + def aspect_ratio(self): + return self.width / self.height @staticmethod def generate_unique_slug(album, datetime_taken): - """Luo yksilöllisen slug-arvon tiedostolle albumin sisällä.""" - slug = int(datetime_taken.strftime('%y%m%d%H%M%S')) - while Photo.objects.filter(album=album, slug=str(slug)).exists(): - slug += 1 - return str(slug) + """ + Luo uniikin slugin, joka perustuu ottopäivämäärään. + Lisää tarvittaessa satunnaisluvun, jos slug on jo olemassa. + """ + base_slug = datetime_taken.strftime('%y%m%d%H%M%S') # esim. 240304153045 + slug = f"{base_slug}{random.randint(0, 9)}" + + while Photo.objects.filter(slug=slug).exists(): + slug = f"{base_slug}{random.randint(10, 99)}" # Jos törmäys, lisää 2 satunnaisnumeroa + + return slug def add_like(self): self.likes += 1 - self.save() + self.save(update_fields=['likes']) def add_view(self): self.views += 1 - self.save() + self.save(update_fields=['views']) def get_next(self): - return self.__class__.objects.filter(taken_at__gt=self.taken_at, album=self.album.id).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): - return self.__class__.objects.filter(taken_at__lt=self.taken_at, album=self.album.id).order_by('-taken_at').first() + return self.__class__.objects.filter(taken_at__lt=self.taken_at, album=self.album).order_by('-taken_at').first() def extract_metadata(self): """Lukee Exif-metadatan ja asettaa tiedot ennen kuvan tallennusta.""" - if self.photo: - try: - exif_data = Exif(self.photo.file) # Suoraan muistista, ei tiedostosta - self.taken_at = getattr(exif_data, 'datetimeoriginal', datetime.now)() - self.exif = getattr(exif_data, 'data', None) - except Exception as e: - print(f"Exif-tiedon lukeminen epäonnistui: {e}") - self.taken_at = datetime.now() + if not self.photo: + return # Jos kuvaa ei ole, ei tehdä mitään + + try: + exif_data = Exif(self.photo.file) # Luetaan Exif-metadata suoraan muistista + self.taken_at = exif_data.datetimeoriginal or datetime.now() + self.exif = exif_data.data or None + except Exception as e: + print(f"Exif-tiedon lukeminen epäonnistui: {e}") + self.taken_at = datetime.now() def save(self, *args, **kwargs): - """Ennen tallennusta luetaan Exif ja asetetaan slug.""" + """Ennen tallennusta luetaan Exif ja asetetaan slug, jos se puuttuu.""" if not self.slug: - self.extract_metadata() + self.extract_metadata() # Varmistetaan, että ottoaika on saatavilla self.slug = self.generate_unique_slug(self.album, self.taken_at or datetime.now()) super().save(*args, **kwargs) @@ -82,8 +94,9 @@ class Photo(models.Model): return reverse('gallery:photo_url', kwargs={'album_slug': self.album.slug, 'photo_slug': self.slug}) class Meta: + constraints = [models.UniqueConstraint(fields=['slug'], name='unique_photo_slug')] verbose_name_plural = "Photos" ordering = ('-taken_at',) def __str__(self): - return f'{self.slug} ({self.orientation}) {self.is_favorite}' + return f'{self.slug} ({self.orientation}) {self.is_favorite}' \ No newline at end of file diff --git a/gallery/templates/gallery/album_detail.html b/gallery/templates/gallery/album_detail.html index 24c9d70..4c22bd5 100644 --- a/gallery/templates/gallery/album_detail.html +++ b/gallery/templates/gallery/album_detail.html @@ -27,20 +27,24 @@
diff --git a/gallery/templates/gallery/photo_list.html b/gallery/templates/gallery/photo_list.html index f316243..b1f937f 100644 --- a/gallery/templates/gallery/photo_list.html +++ b/gallery/templates/gallery/photo_list.html @@ -31,10 +31,14 @@ {{ photo.photo_sm.url }} 320w, {{ photo.photo_md.url }} 720w, {{ photo.photo_bg.url }} 1920w - " - sizes="(max-width: 640px) 320px, - (max-width: 960px) 720px, - 1920px" + " + sizes="(max-width: 640px) 50vw, + (max-width: 960px) 33vw, + (max-width: 1200px) 25vw, + 20vw" + width="{{ photo.width }}" + height="{{ photo.height }}" + style="aspect-ratio: {{ photo.aspect_ratio }};" alt="{{ photo.album.name }} - {{ photo.slug }}"> {% endfor %}