diff --git a/galerie/migrations/0006_django_imagekit.py b/galerie/migrations/0006_django_imagekit.py new file mode 100644 index 00000000..6b90b791 --- /dev/null +++ b/galerie/migrations/0006_django_imagekit.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('galerie', '0005_obrazek_ordering_datum'), + ] + + operations = [ + migrations.RemoveField( + model_name='obrazek', + name='obrazek_maly', + ), + migrations.RemoveField( + model_name='obrazek', + name='obrazek_stredni', + ), + ] diff --git a/galerie/models.py b/galerie/models.py index 22457ba1..9d55a3bf 100644 --- a/galerie/models.py +++ b/galerie/models.py @@ -5,6 +5,8 @@ import seminar.models from django.db.models import Q from django.utils import timezone from django.utils.encoding import force_unicode +from imagekit.models import ImageSpecField +from imagekit.processors import ResizeToFit, Transpose from PIL import Image from PIL.ExifTags import TAGS @@ -32,47 +34,32 @@ def get_exif(fn): 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 - ] - +# 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): - 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)) + return os.path.join('Galerie', "soustredeni_" + force_unicode(gal.soustredeni.pk), "galerie_" + cislo_gal, "velky", 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) + 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) @@ -89,55 +76,10 @@ class Obrazek(models.Model): 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) + datum_ints = map(int, ":".join(exif['DateTimeOriginal'].split(' ')).split(":")) + self.datum = datetime(*datum_ints) 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): diff --git a/galerie/templates/galerie/GalerieNahled.html b/galerie/templates/galerie/GalerieNahled.html index 1a4656b4..9a26f101 100644 --- a/galerie/templates/galerie/GalerieNahled.html +++ b/galerie/templates/galerie/GalerieNahled.html @@ -45,8 +45,8 @@ Galerie {{galerie.nazev}} {% if galerie.titulni_obrazek %} {% with galerie.titulni_obrazek.obrazek_maly as obrazek %} + width="{{ obrazek.width }}" + height="{{ obrazek.height }}" /> {% endwith %} {% endif %}
@@ -76,8 +76,8 @@ Galerie {{galerie.nazev}} {% for obrazek in obrazky %} + width="{{ obrazek.obrazek_maly.width }}" + height="{{ obrazek.obrazek_maly.height }}" /> {% endfor %}
diff --git a/requirements.txt b/requirements.txt index ea1261ee..4003e290 100644 --- a/requirements.txt +++ b/requirements.txt @@ -23,6 +23,7 @@ django-flat-theme==0.9.3 django-taggit==0.17 django-autocomplete-light==2.2.6 django-crispy-forms==1.4.0 +django-imagekit==3.2.7 # Comments akismet==0.2.0 diff --git a/seminar/migrations/0035_django_imagekit.py b/seminar/migrations/0035_django_imagekit.py new file mode 100644 index 00000000..dd443018 --- /dev/null +++ b/seminar/migrations/0035_django_imagekit.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +import imagekit.models.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('seminar', '0034_reseni_forma_default_email'), + ] + + operations = [ + migrations.RemoveField( + model_name='organizator', + name='foto_male', + ), + migrations.AlterField( + model_name='organizator', + name='foto', + field=imagekit.models.fields.ProcessedImageField(help_text=b'Vlo\xc5\xbe fotografii organiz\xc3\xa1tora o libovoln\xc3\xa9 velikosti', upload_to=b'image_organizatori/velke/%Y/', null=True, verbose_name=b'Fotografie organiz\xc3\xa1tora', blank=True), + preserve_default=True, + ), + ] diff --git a/seminar/models.py b/seminar/models.py index 0f65c272..47f71e5f 100644 --- a/seminar/models.py +++ b/seminar/models.py @@ -11,6 +11,8 @@ from django.utils.encoding import force_unicode from django.utils.text import slugify from django.core.urlresolvers import reverse from django.core.cache import cache +from imagekit.models import ImageSpecField, ProcessedImageField +from imagekit.processors import ResizeToFit, Transpose from PIL import Image import os @@ -785,11 +787,19 @@ class Organizator(models.Model): "'Přednáší na MFF'") strucny_popis_organizatora = models.TextField('Stručný popis organizátora', null = True, blank = True) - foto = models.ImageField('Fotografie organizátora', + foto = ProcessedImageField(verbose_name='Fotografie organizátora', upload_to='image_organizatori/velke/%Y/', null = True, blank = True, - help_text = 'Vlož fotografii organizátora o libovolné velikosti') - foto_male = models.ImageField(upload_to='image_organizatori/male/%Y/', - null = True, blank = True, editable = False) + help_text = 'Vlož fotografii organizátora o libovolné velikosti', + processors=[ + Transpose(Transpose.AUTO), + ResizeToFit(500, 500, upscale=False) + ], + options={'quality': 95}) + foto_male = ImageSpecField(source='foto', + processors=[ + ResizeToFit(200, 200, upscale=False) + ], + options={'quality': 95}) def __str__(self): return str(self.user) @@ -797,52 +807,3 @@ class Organizator(models.Model): class Meta: verbose_name = 'Organizátor' verbose_name_plural = 'Organizátoři' - - def save(self): - # v databázi uložený záznam o organizátorovi - puvodni = None - - # pokud už organizátor v databázi existuje, nastav puvodni - if self.id is not None: - puvodni = Organizator.objects.get(id=self.id) - # pokud nahráváme fotku - if self.foto: - # a je jiná než ta stará - if not puvodni or puvodni.foto != self.foto: - # uložíme ji - original = Image.open(self.foto) - jmeno = os.path.basename(self.foto.file.name) - Organizator._vyrobMiniaturu(original, jmeno, 500, self.foto) - Organizator._vyrobMiniaturu(original, jmeno, 200, self.foto_male) - super(Organizator, self).save() - - @staticmethod - def _vyrobMiniaturu(original, jmeno, maximum, field): - zmensenina = Organizator._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 = Organizator._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)) -