Merge branch 'imagekit'
This commit is contained in:
commit
4243e1cd00
6 changed files with 85 additions and 134 deletions
22
galerie/migrations/0006_django_imagekit.py
Normal file
22
galerie/migrations/0006_django_imagekit.py
Normal file
|
@ -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',
|
||||||
|
),
|
||||||
|
]
|
|
@ -5,6 +5,8 @@ import seminar.models
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.encoding import force_unicode
|
from django.utils.encoding import force_unicode
|
||||||
|
from imagekit.models import ImageSpecField
|
||||||
|
from imagekit.processors import ResizeToFit, Transpose
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from PIL.ExifTags import TAGS
|
from PIL.ExifTags import TAGS
|
||||||
|
@ -32,47 +34,32 @@ def get_exif(fn):
|
||||||
ret[decoded] = value
|
ret[decoded] = value
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def flip_horizontal(im): return im.transpose(Image.FLIP_LEFT_RIGHT)
|
# tyhle funkce jsou tady jen kvůli starým migracím, které se na ně odkazují
|
||||||
def flip_vertical(im): return im.transpose(Image.FLIP_TOP_BOTTOM)
|
# až se ty migrace někdy squashnou, tak by mělo být možné funkce smazat
|
||||||
def rotate_180(im): return im.transpose(Image.ROTATE_180)
|
def obrazek_filename_maly():
|
||||||
def rotate_90(im): return im.transpose(Image.ROTATE_90)
|
pass
|
||||||
def rotate_270(im): return im.transpose(Image.ROTATE_270)
|
def obrazek_filename_stredni():
|
||||||
def transpose(im): return rotate_90(flip_horizontal(im))
|
pass
|
||||||
def transverse(im): return rotate_90(flip_vertical(im))
|
def obrazek_filename_velky():
|
||||||
orientation_funcs = [None,
|
pass
|
||||||
lambda x: x,
|
|
||||||
flip_horizontal,
|
|
||||||
rotate_180,
|
|
||||||
flip_vertical,
|
|
||||||
transpose,
|
|
||||||
rotate_270,
|
|
||||||
transverse,
|
|
||||||
rotate_90
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def obrazek_filename(self, filename):
|
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
|
gal = self.galerie
|
||||||
cislo_gal = force_unicode(gal.pk)
|
cislo_gal = force_unicode(gal.pk)
|
||||||
cesta = ""
|
cesta = ""
|
||||||
while(not gal.soustredeni):
|
while(not gal.soustredeni):
|
||||||
gal = gal.galerie_up
|
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):
|
class Obrazek(models.Model):
|
||||||
obrazek_velky = models.ImageField(upload_to=obrazek_filename,
|
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.")
|
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_stredni = ImageSpecField(source='obrazek_velky',
|
||||||
obrazek_maly = models.ImageField(upload_to=obrazek_filename_maly, null = True, editable = False)
|
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)
|
nazev = models.CharField('Název', max_length=50, blank = True, null = True)
|
||||||
popis = models.TextField('Popis', blank = True, null = True)
|
popis = models.TextField('Popis', blank = True, null = True)
|
||||||
datum_vlozeni = models.DateTimeField('Datum vložení', auto_now_add = 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)
|
original = Image.open(self.obrazek_velky)
|
||||||
# vycteni EXIFu
|
# vycteni EXIFu
|
||||||
exif = get_exif(original)
|
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']:
|
if exif['DateTimeOriginal']:
|
||||||
datum_string = ":".join(exif['DateTimeOriginal'].split(' ')).split(":")
|
datum_ints = map(int, ":".join(exif['DateTimeOriginal'].split(' ')).split(":"))
|
||||||
datum_int = []
|
self.datum = datetime(*datum_ints)
|
||||||
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()
|
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):
|
class Galerie(models.Model):
|
||||||
|
|
|
@ -45,8 +45,8 @@ Galerie {{galerie.nazev}}
|
||||||
{% if galerie.titulni_obrazek %}
|
{% if galerie.titulni_obrazek %}
|
||||||
{% with galerie.titulni_obrazek.obrazek_maly as obrazek %}
|
{% with galerie.titulni_obrazek.obrazek_maly as obrazek %}
|
||||||
<img src="{{ obrazek.url }}"
|
<img src="{{ obrazek.url }}"
|
||||||
width={% widthratio obrazek.width 200 167 %}
|
width="{{ obrazek.width }}"
|
||||||
height={% widthratio obrazek.height 200 167 %} />
|
height="{{ obrazek.height }}" />
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div>
|
<div>
|
||||||
|
@ -76,8 +76,8 @@ Galerie {{galerie.nazev}}
|
||||||
{% for obrazek in obrazky %}
|
{% for obrazek in obrazky %}
|
||||||
<a title="Zobrazit tuto fotografii" href="./{{obrazek.pk}}#nahoru" class="galerie_nahled"><span class="vystredeno"></span><img
|
<a title="Zobrazit tuto fotografii" href="./{{obrazek.pk}}#nahoru" class="galerie_nahled"><span class="vystredeno"></span><img
|
||||||
src="{{obrazek.obrazek_maly.url}}"
|
src="{{obrazek.obrazek_maly.url}}"
|
||||||
width={% widthratio obrazek.obrazek_maly.width 200 167 %}
|
width="{{ obrazek.obrazek_maly.width }}"
|
||||||
height={% widthratio obrazek.obrazek_maly.height 200 167 %} />
|
height="{{ obrazek.obrazek_maly.height }}" />
|
||||||
</a>
|
</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<br>
|
<br>
|
||||||
|
|
|
@ -23,6 +23,7 @@ django-flat-theme==0.9.3
|
||||||
django-taggit==0.17
|
django-taggit==0.17
|
||||||
django-autocomplete-light==2.2.6
|
django-autocomplete-light==2.2.6
|
||||||
django-crispy-forms==1.4.0
|
django-crispy-forms==1.4.0
|
||||||
|
django-imagekit==3.2.7
|
||||||
|
|
||||||
# Comments
|
# Comments
|
||||||
akismet==0.2.0
|
akismet==0.2.0
|
||||||
|
|
25
seminar/migrations/0035_django_imagekit.py
Normal file
25
seminar/migrations/0035_django_imagekit.py
Normal file
|
@ -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,
|
||||||
|
),
|
||||||
|
]
|
|
@ -11,6 +11,8 @@ from django.utils.encoding import force_unicode
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
|
from imagekit.models import ImageSpecField, ProcessedImageField
|
||||||
|
from imagekit.processors import ResizeToFit, Transpose
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
import os
|
import os
|
||||||
|
@ -785,11 +787,19 @@ class Organizator(models.Model):
|
||||||
"'Přednáší na MFF'")
|
"'Přednáší na MFF'")
|
||||||
strucny_popis_organizatora = models.TextField('Stručný popis organizátora',
|
strucny_popis_organizatora = models.TextField('Stručný popis organizátora',
|
||||||
null = True, blank = True)
|
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,
|
upload_to='image_organizatori/velke/%Y/', null = True, blank = True,
|
||||||
help_text = 'Vlož fotografii organizátora o libovolné velikosti')
|
help_text = 'Vlož fotografii organizátora o libovolné velikosti',
|
||||||
foto_male = models.ImageField(upload_to='image_organizatori/male/%Y/',
|
processors=[
|
||||||
null = True, blank = True, editable = False)
|
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):
|
def __str__(self):
|
||||||
return str(self.user)
|
return str(self.user)
|
||||||
|
@ -797,52 +807,3 @@ class Organizator(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = 'Organizátor'
|
verbose_name = 'Organizátor'
|
||||||
verbose_name_plural = 'Organizátoři'
|
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))
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue