from django.db import models #from django.db.models import Q from imagekit.models import ImageSpecField from imagekit.processors import ResizeToFit, Transpose import os from soustredeni.models import Soustredeni VZDY=0 ORG=1 NIKDY=2 UCASTNIK=3 VIDITELNOST = ( (VZDY, 'Vždy'), (ORG, 'Organizátorům'), (UCASTNIK, 'Účastníkům a orgům'), (NIKDY, 'Nikdy'), ) # tyhle funkce jsou tady jen kvůli starým migracím, které se na ně odkazují # až se ty migrace někdy squashnou, tak by mělo být možné funkce smazat def obrazek_filename_maly(): pass def obrazek_filename_stredni(): pass def obrazek_filename_velky(): pass def obrazek_filename(self, filename): gal = self.galerie cislo_gal = gal.pk # najdi kořenovou galerii while (gal.galerie_up): gal = gal.galerie_up # soustředění je v cestě jen pokud galerie pod nějaké patří cesta = ( ['Galerie'] + (["soustredeni_{}".format(gal.soustredeni.pk)] if gal.soustredeni else []) + ["galerie_{}".format(cislo_gal), self.nazev] ) return os.path.join(*cesta) class Obrazek(models.Model): obrazek_velky = models.ImageField(upload_to=obrazek_filename, help_text = "Lze vložit libovolně velký obrázek. Ideální je, aby alespoň jeden rozměr měl alespoň 500px.") obrazek_stredni = ImageSpecField(source='obrazek_velky', processors=[Transpose(Transpose.AUTO), ResizeToFit(900, 675, upscale=False)], options={'quality': 95}) obrazek_maly = ImageSpecField(source='obrazek_velky', processors=[Transpose(Transpose.AUTO), ResizeToFit(167, 167, upscale=False)], options={'quality': 95}) nazev = models.CharField('Název', max_length=50, blank=True, null=True) popis = models.TextField('Popis', blank=True, null=True) datum_vlozeni = models.DateTimeField('Datum vložení', auto_now_add=True) galerie = models.ForeignKey('Galerie', blank=True, null=True, on_delete=models.CASCADE) poradi = models.IntegerField('Pořadí', blank=True, null=True) def __str__(self): return self.obrazek_velky.name class Meta: verbose_name = 'Obrázek' verbose_name_plural = 'Obrázky' ordering = ['nazev'] def obrazek_maly_tag(self): if not self.obrazek_maly: return '' return u''.format(self.obrazek_maly.url) obrazek_maly_tag.short_description = "Náhled" obrazek_maly_tag.allow_tags = True def save(self, *args, **kwargs): # obrázek potřebuje název, protože se z něj generuje cesta pro jeho uložení # (a pak se podle něj taky řadí) if self.nazev is None: self.nazev = os.path.basename(self.obrazek_velky.name) super(Obrazek, self).save(*args, **kwargs) class Galerie(models.Model): nazev = models.CharField('Název', max_length=100) datum_vytvoreni = models.DateTimeField('Datum vytvoření', auto_now_add = True) datum_zmeny = models.DateTimeField('Datum poslední změny', auto_now = True) popis = models.TextField('Popis', blank = True, null = True) titulni_obrazek = models.ForeignKey(Obrazek, blank = True, null = True, related_name = "+", on_delete = models.SET_NULL) zobrazit = models.IntegerField('Zobrazit?', default = ORG, choices = VIDITELNOST) galerie_up = models.ForeignKey('Galerie', blank = True, null = True, on_delete=models.PROTECT) soustredeni = models.ForeignKey(Soustredeni, blank = True, null = True, on_delete=models.PROTECT) poradi = models.IntegerField('Pořadí', blank = True, null = False, default = 0) def __str__(self): return self.nazev class Meta: verbose_name = 'Galerie' verbose_name_plural = 'Galerie' # TODO: patří to spíš sem, nebo do nějakých utils? def setrid_galerii_podle_exifu(self): """Setřídí galerii podle data v EXIF tazích. Velmi experimentální, zatím pro použití jen webařem v shellu (důvod: EXIF se trochu blbě parsuje, není jasné, jestli se má použít DateTime, DateTimeOriginal nebo DateTimeDigitized, EXIF nemusí mít informace o časové zóně a tenhle kód časovou zónu ignoruje, vůbec nezachovává pořadí).""" from PIL import Image, ExifTags, UnidentifiedImageError from datetime import datetime EXIF_DATETIME_FMT = "%Y:%m:%d %H:%M:%S" self.obrazek_set.update(poradi=None) for obrazek in self.obrazek_set.all(): try: obr = Image.open(obrazek.obrazek_velky) except UnidentifiedImageError as e: raise ValueError from e exif = obr.getexif() # Pokud tam není, tak si Pillow podle zdrojáků vyhaluzí prázdný. date_str = exif.get(ExifTags.Base.DateTime, None) or exif.get(ExifTags.Base.DateTimeOriginal, None) or exif.get(ExifTags.Base.DateTimeDigitized, None) if date_str is None: continue dt = datetime.strptime(date_str, EXIF_DATETIME_FMT) poradi = int(dt.strftime("1%d%H%M%S")) obrazek.poradi = poradi obrazek.save()