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.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): | ||||
|  |  | |||
|  | @ -45,8 +45,8 @@ Galerie {{galerie.nazev}} | |||
|             {% if galerie.titulni_obrazek %} | ||||
|             {% with galerie.titulni_obrazek.obrazek_maly as obrazek %} | ||||
|             <img src="{{ obrazek.url }}" | ||||
|                 width={% widthratio obrazek.width 200 167 %} | ||||
|                 height={% widthratio obrazek.height 200 167 %} /> | ||||
|                 width="{{ obrazek.width }}" | ||||
|                 height="{{ obrazek.height }}" /> | ||||
|             {% endwith %} | ||||
|             {% endif %} | ||||
|             <div> | ||||
|  | @ -76,8 +76,8 @@ Galerie {{galerie.nazev}} | |||
|     {% for obrazek in obrazky %} | ||||
|         <a title="Zobrazit tuto fotografii" href="./{{obrazek.pk}}#nahoru" class="galerie_nahled"><span class="vystredeno"></span><img | ||||
|             src="{{obrazek.obrazek_maly.url}}" | ||||
|             width={% widthratio obrazek.obrazek_maly.width 200 167 %} | ||||
|             height={% widthratio obrazek.obrazek_maly.height 200 167 %} /> | ||||
|             width="{{ obrazek.obrazek_maly.width }}" | ||||
|             height="{{ obrazek.obrazek_maly.height }}" /> | ||||
|         </a> | ||||
|     {% endfor %} | ||||
|     <br> | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
							
								
								
									
										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.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)) | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Matěj Kocián
						Matěj Kocián