# coding: utf-8 from django.db import models import seminar.models from django.db.models import Q from django.utils import timezone from django.utils.encoding import force_unicode from PIL import Image from PIL.ExifTags import TAGS import os from cStringIO import StringIO from django.core.files.base import ContentFile from datetime import datetime from seminar.models import Soustredeni VZDY=0 ORG=1 NIKDY=2 VIDITELNOST = ( (VZDY, 'Vždy'), (ORG, 'Organizátorům'), (NIKDY, 'Nikdy'), ) def get_exif(fn): ret = {} info = fn._getexif() for tag, value in info.items(): decoded = TAGS.get(tag, tag) ret[decoded] = value return ret def flip_horizontal(im): return im.transpose(Image.FLIP_LEFT_RIGHT) def flip_vertical(im): return im.transpose(Image.FLIP_TOP_BOTTOM) def rotate_180(im): return im.transpose(Image.ROTATE_180) def rotate_90(im): return im.transpose(Image.ROTATE_90) def rotate_270(im): return im.transpose(Image.ROTATE_270) def transpose(im): return rotate_90(flip_horizontal(im)) def transverse(im): return rotate_90(flip_vertical(im)) orientation_funcs = [None, lambda x: x, flip_horizontal, rotate_180, flip_vertical, transpose, rotate_270, transverse, rotate_90 ] def obrazek_filename(self, filename): return obrazek_filename_obecny(self, filename, "velky") def obrazek_filename_stredni(self, filename): return obrazek_filename_obecny(self, filename, "stredni") def obrazek_filename_maly(self, filename): return obrazek_filename_obecny(self, filename, "maly") def obrazek_filename_obecny(self, filename, typ): gal = self.galerie cislo_gal = force_unicode(gal.pk) cesta = "" while(not gal.soustredeni): gal = gal.galerie_up return os.path.join('Galerie', "soustredeni_" + force_unicode(gal.soustredeni.pk), "galerie_" + cislo_gal, typ, force_unicode(self.nazev)) 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 = models.ImageField(upload_to=obrazek_filename_stredni, null = True, editable = False) obrazek_maly = models.ImageField(upload_to=obrazek_filename_maly, null = True, editable = False) 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) datum = models.DateTimeField('Datum pořízení fotografie', blank = True, null = True) galerie = models.ForeignKey('Galerie', blank=True, null=True) poradi = models.IntegerField('Pořadí', blank = True, null = True) def __unicode__(self): return self.nazev + " -- " + unicode(self.obrazek_velky.name) + " (" + str(self.datum) + ")" class Meta: verbose_name = 'Obrázek' verbose_name_plural = 'Obrázky' ordering = ['datum'] def save(self): original = Image.open(self.obrazek_velky) # vycteni EXIFu exif = get_exif(original) # otoceni podle EXIFu if exif['Orientation']: f = orientation_funcs[exif['Orientation']] original_otoceny = f(original) original_otoceny.format = original.format original = original_otoceny # datum podle EXIfu if exif['DateTimeOriginal']: datum_string = ":".join(exif['DateTimeOriginal'].split(' ')).split(":") datum_int = [] for retezec in datum_string: datum_int.append(int(retezec)) self.datum = datetime(datum_int[0], datum_int[1], datum_int[2], datum_int[3], datum_int[4], datum_int[5]) jmeno = os.path.basename(self.obrazek_velky.file.name) if not self.obrazek_stredni: Obrazek._vyrobMiniaturu(original, jmeno, 1024, self.obrazek_stredni) if not self.obrazek_maly: Obrazek._vyrobMiniaturu(original, jmeno, 200, self.obrazek_maly) super(Obrazek, self).save() @staticmethod def _vyrobMiniaturu(original, jmeno, maximum, field): zmensenina = Obrazek._zmensiObrazek(original, maximum) f = StringIO() try: zmensenina.save(f, format=original.format) data = ContentFile(f.getvalue()) finally: f.close() field.save(jmeno, data, save = False) @staticmethod def _zmensiObrazek(original, maximum): """Preskaluje obrazek tak, aby byl zachovan pomer stran a zadny rozmer nepresahoval maxRozmer. Pokud zadny rozmer nepresahuje maxRozmer, tak vrati puvodni obrazek (tj. nedojde ke zvetseni obrazku).""" novaVelikost = Obrazek._zmensiVelikost(original.size, maximum) return original.resize(novaVelikost, Image.ANTIALIAS) @staticmethod def _zmensiVelikost(velikost, maximum): maximum = float(maximum) w, h = velikost soucasneMaximum = max(w, h) if soucasneMaximum <= maximum: return velikost pomer = maximum/soucasneMaximum return (int(w * pomer), int(h * pomer)) 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) soustredeni = models.ForeignKey(Soustredeni, blank = True, null = True) poradi = models.IntegerField('Pořadí', blank = True, null = True) def __unicode__(self): return self.nazev class Meta: verbose_name = 'Galerie' verbose_name_plural = 'Galerie' #def link_na_preview(self): #"""Odkaz na galerii, používá se v admin rozhranní. """ #return 'Preview' % self.id #link_na_preview.allow_tags = True #link_na_preview.short_description = 'Zobrazit galerii' # #def je_publikovano(self): #"""Vraci True, pokud je tato galerie publikovana. """ #if self.zobrazit == VZDY: #return True #if self.zobrazit == PODLE_CLANKU: #for clanek in self.clanek_set.all(): #if clanek.je_publikovano(): #return True #return False # #@staticmethod #def publikovane_galerie(): #"""Vraci galerie, ktere uz maji byt publikovane.""" #clanky = Blog.models.Clanek.publikovane_clanky() #return Galerie.objects.filter(Q(zobrazit=VZDY) | (Q(clanek__in=clanky) & Q(zobrazit=PODLE_CLANKU))).distinct()