diff options
Diffstat (limited to 'app/media/models.py')
-rw-r--r-- | app/media/models.py | 215 |
1 files changed, 130 insertions, 85 deletions
diff --git a/app/media/models.py b/app/media/models.py index 190026f..dcf7ccc 100644 --- a/app/media/models.py +++ b/app/media/models.py @@ -1,28 +1,28 @@ import os.path import io import datetime +from pathlib import Path from PIL import Image from django.core.exceptions import ValidationError -from django.db import models +from django.contrib.gis.db import models from django.contrib.sitemaps import Sitemap -from django.utils.encoding import force_text +from django.db.models.signals import post_save +from django.dispatch import receiver +from django.db.models.signals import m2m_changed from django.utils.functional import cached_property from django.urls import reverse from django.apps import apps from django.utils.html import format_html -from django.utils.text import slugify from django.conf import settings from django import forms -from taggit.managers import TaggableManager - from resizeimage.imageexceptions import ImageSizeError +from taggit.managers import TaggableManager + +from .readexif import readexif from .utils import resize_image -from django.db.models.signals import post_save -from django.dispatch import receiver -from django.db.models.signals import m2m_changed def get_upload_path(self, filename): @@ -39,6 +39,7 @@ def get_audio_upload_path(self, filename): class LuxImageSize(models.Model): name = models.CharField(null=True, blank=True, max_length=30) + slug = models.SlugField(null=True, blank=True) width = models.IntegerField(null=True, blank=True) height = models.IntegerField(null=True, blank=True) quality = models.IntegerField() @@ -63,10 +64,21 @@ class LuxImage(models.Model): photo_credit_url = models.CharField(null=True, blank=True, max_length=300) caption = models.TextField(blank=True, null=True) pub_date = models.DateTimeField(default=datetime.datetime.now) + exif_raw = models.TextField(blank=True, null=True) + exif_aperture = models.CharField(max_length=50, blank=True, null=True) + exif_make = models.CharField(max_length=50, blank=True, null=True) + exif_model = models.CharField(max_length=50, blank=True, null=True) + exif_exposure = models.CharField(max_length=50, blank=True, null=True) + exif_iso = models.CharField(max_length=50, blank=True, null=True) + exif_focal_length = models.CharField(max_length=50, blank=True, null=True) + exif_lens = models.CharField(max_length=50, blank=True, null=True) + exif_date = models.DateTimeField(blank=True, null=True) height = models.CharField(max_length=6, blank=True, null=True) width = models.CharField(max_length=6, blank=True, null=True) + point = models.PointField(null=True, blank=True) is_public = models.BooleanField(default=True) - sizes = models.ManyToManyField(LuxImageSize, blank=True) + sizes = models.ManyToManyField(LuxImageSize, blank=True, related_name='sizes') + sizes_cache = models.CharField(null=True, blank=True, max_length=300) class Meta: ordering = ('-pub_date', 'id') @@ -85,10 +97,7 @@ class LuxImage(models.Model): def get_admin_image(self): for size in self.sizes.all(): if size.width and size.width <= 820 or size.height and size.height <= 800: - return self.get_image_by_size(size.name) - - def get_admin_insert(self): - return "/media/images/%s/%s_tn.%s" % (self.pub_date.strftime("%Y"), self.get_image_name(), self.get_image_ext()) + return self.get_image_url_by_size(size.name) def get_largest_image(self): t = [] @@ -98,74 +107,70 @@ class LuxImage(models.Model): t.reverse() return self.get_image_path_by_size(t[0]) - def get_image_name(self): - return self.image.url.split("original/")[1][5:-4] - - def get_image_ext(self): - return self.image.url[-3:] - @cached_property - def get_featured_jrnl(self): - ''' cached version of getting the primary image for archive page''' - return "%s%s/%s_%s.%s" % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), self.get_image_name(), 'featured_jrnl', self.get_image_ext()) + def image_name(self): + return os.path.basename(self.image.path)[:-4] @cached_property - def get_picwide_sm(self): - ''' cached version of getting the second image for archive page''' - return "%s%s/%s_%s.%s" % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), self.get_image_name(), 'picwide-sm', self.get_image_ext()) + def image_ext(self): + return self.image.url[-3:] @cached_property + def get_image_filename(self): + return os.path.basename(self.image.path) + + @property def get_srcset(self): srcset = "" length = len(self.sizes.all()) print(length) loopnum = 1 for size in self.sizes.all(): - srcset += "%s%s/%s_%s.%s %sw" % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), self.get_image_name(), size.name, self.get_image_ext(), size.width) + srcset += "%s%s/%s_%s.%s %sw" % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), self.image_name, size.slug, self.image_ext, size.width) if loopnum < length: srcset += ", " loopnum = loopnum+1 return srcset - @cached_property + @property def get_src(self): src = "" if self.sizes.all().count() > 1: - src += "%s%s/%s_%s.%s" % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), self.get_image_name(), 'picwide-med', self.get_image_ext()) + src = self.get_image_url_by_size('picwide-med') else: - src += "%s%s/%s_%s.%s" % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), self.get_image_name(), [size.name for size in self.sizes.all()], self.get_image_ext()) + size = "".join(size.name for size in self.sizes.all()) + src = self.get_image_url_by_size(size) return src - def get_image_by_size(self, size="original"): - base = self.get_image_name() - if size == "admin_insert": - return "images/%s/%s.%s" % (self.pub_date.strftime("%Y"), base, self.get_image_ext()) + def get_image_url_by_size(self, size="original"): if size == "original": - return "%soriginal/%s/%s.%s" % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), base, self.get_image_ext()) + return "%soriginal/%s/%s.%s" % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), self.image_name, self.image_ext) + if size == "admin_insert": + return "images/%s/%s.%s" % (self.pub_date.strftime("%Y"), self.image_name, self.image_ext) else: - if size != 'tn': - s = LuxImageSize.objects.get(name=size) - if s not in self.sizes.all(): - print("new size is "+s.name) - self.sizes.add(s) - return "%s%s/%s_%s.%s" % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), base, size, self.get_image_ext()) + luximagesize = LuxImageSize.objects.get(slug=size) + #if luximagesize not in self.get_sizes: + #self.sizes.add(luximagesize) + return "%s%s/%s_%s.%s" % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), self.image_name, luximagesize.slug, self.image_ext) def get_image_path_by_size(self, size="original"): - base = self.get_image_name() if size == "original": - return "%s/original/%s/%s.%s" % (settings.IMAGES_ROOT, self.pub_date.strftime("%Y"), base, self.get_image_ext()) + return self.image.path else: - return "%s/%s/%s_%s.%s" % (settings.IMAGES_ROOT, self.pub_date.strftime("%Y"), base, size, self.get_image_ext()) + luximagesize = LuxImageSize.objects.get(slug=size) + return "%s/%s/%s_%s.%s" % (settings.IMAGES_ROOT, self.pub_date.strftime("%Y"), self.image_name, luximagesize.slug, self.image_ext) + @cached_property def get_thumbnail_url(self): - return self.get_image_by_size("tn") + return self.get_image_url_by_size("tn") def admin_thumbnail(self): - return format_html('<a href="%s"><img src="%s"></a>' % (self.get_image_by_size(), self.get_image_by_size("tn"))) + return format_html('<a href="%s"><img src="%s"></a>' % (self.get_image_url_by_size(), self.get_image_url_by_size("tn"))) admin_thumbnail.short_description = 'Thumbnail' + @property def get_sizes(self): - return self.sizes.all() + return self.sizes_cache.split(",") @property def get_previous_published(self): @@ -196,6 +201,9 @@ class LuxImage(models.Model): return False def save(self, *args, **kwargs): + created = self.pk is None + if not created: + self.sizes_cache = ",".join(s.slug for s in self.sizes.all()) super(LuxImage, self).save() @@ -270,6 +278,7 @@ class LuxAudio(models.Model): pub_date = models.DateTimeField(default=datetime.datetime.now) mp3 = models.FileField(blank=True, null=True, upload_to=get_audio_upload_path) ogg = models.FileField(blank=True, null=True, upload_to=get_audio_upload_path) + point = models.PointField(blank=True, null=True) class Meta: ordering = ('-pub_date',) @@ -283,6 +292,9 @@ class LuxAudio(models.Model): def get_absolute_url(self): return reverse("prompt:detail", kwargs={"slug": self.slug}) + def get_image_url_by_size(self, size="original"): + pass + @property def get_previous_published(self): return self.get_previous_by_pub_date(status__exact=1) @@ -310,51 +322,84 @@ class LuxAudio(models.Model): def save(self, *args, **kwargs): md = render_images(self.body_markdown) self.body_html = markdown_to_html(md) + if not self.point: + self.point = CheckIn.objects.latest().point super(LuxAudio, self).save(*args, **kwargs) @receiver(post_save, sender=LuxImage) def post_save_events(sender, update_fields, created, instance, **kwargs): - if instance.exif_raw == '': - filename, file_extension = os.path.splitext(instance.image.path) - if file_extension != ".mp4": - img = Image.open(instance.image.path) - instance.height = img.height - instance.width = img.width - post_save.disconnect(post_save_events, sender=LuxImage) - instance.save() - post_save.connect(post_save_events, sender=LuxImage) + if created: + if instance.exif_raw == '': + instance = readexif(instance) + instance.sizes.add(LuxImageSize.objects.get(slug="tn")) + img = Image.open(instance.image.path) + instance.height = img.height + instance.width = img.width + post_save.disconnect(post_save_events, sender=LuxImage) + instance.save() + post_save.connect(post_save_events, sender=LuxImage) @receiver(m2m_changed, sender=LuxImage.sizes.through) def update_photo_sizes(sender, instance, **kwargs): - base_path = "%s/%s/" % (settings.IMAGES_ROOT, instance.pub_date.strftime("%Y")) - filename, file_extension = os.path.splitext(instance.image.path) - if file_extension != ".mp4": - img = Image.open(instance.image.path) - resize_image(img, 160, None, 78, base_path, "%s_tn.%s" % (instance.get_image_name(), instance.get_image_ext())) - for size in instance.sizes.all(): - if size.width: - print("Image width is:"+str(img.width)) - try: - if size.width <= img.width: - resize_image(img, size.width, None, size.quality, base_path, "%s_%s.%s" % (instance.get_image_name(), slugify(size.name), instance.get_image_ext())) - else: - raise ValidationError({'items': ["Size is larger than source image"]}) - except ImageSizeError: - m2m_changed.disconnect(update_photo_sizes, sender=LuxImage.sizes.through) - instance.sizes.remove(size) - m2m_changed.connect(update_photo_sizes, sender=LuxImage.sizes.through) - if size.height: - try: - if size.height <= img.height: - resize_image(img, None, size.height, size.quality, base_path, "%s_%s.%s" % (instance.get_image_name(), slugify(size.name), instance.get_image_ext())) - - else: - pass - except ImageSizeError: - m2m_changed.disconnect(update_photo_sizes, sender=LuxImage.sizes.through) - instance.sizes.remove(size) - m2m_changed.connect(update_photo_sizes, sender=LuxImage.sizes.through) - - + # update the local cache of sizes + sizes = instance.sizes.all() + if sizes: + instance.sizes_cache = ",".join(s.slug for s in sizes) + instance.save() + for size in instance.get_sizes: + print("SIZE is: %s" % size) + # check each size and see if there's an image there already + my_file = Path(instance.get_image_path_by_size(size)) + if not my_file.is_file(): + #file doesn't exist, so create it + new_size = LuxImageSize.objects.get(slug=size) + if new_size.width: + img = Image.open(instance.image.path) + try: + if new_size.width <= img.width: + resize_image(img, new_size.width, None, new_size.quality, instance.get_image_path_by_size(size)) + else: + raise ValidationError({'items': ["Size is larger than source image"]}) + except ImageSizeError: + m2m_changed.disconnect(update_photo_sizes, sender=LuxImage.sizes.through) + instance.sizes.remove(new_size) + m2m_changed.connect(update_photo_sizes, sender=LuxImage.sizes.through) + if new_size.height: + img = Image.open(instance.image.path) + try: + if new_size.height <= img.height: + resize_image(img, None, new_size.height, new_size.quality, instance.get_image_path_by_size(size)) + else: + pass + except ImageSizeError: + m2m_changed.disconnect(update_photo_sizes, sender=LuxImage.sizes.through) + instance.sizes.remove(new_size) + m2m_changed.connect(update_photo_sizes, sender=LuxImage.sizes.through) + else: + # file exists, might add something here to force it to do the above when I want + print("file %s exists" % size) + pass + + +def generate_image(luximage, size): + new_size = LuxImageSize.objects.get(slug=size) + if new_size.width: + img = Image.open(luximage.image.path) + try: + if new_size.width <= img.width: + resize_image(img, new_size.width, None, new_size.quality, luximage.get_image_path_by_size(size)) + else: + raise ValidationError({'items': ["Size is larger than source image"]}) + except ImageSizeError: + print("error creating size") + if new_size.height: + img = Image.open(luximage.image.path) + try: + if new_size.height <= img.height: + resize_image(img, None, new_size.height, new_size.quality, luximage.get_image_path_by_size(size)) + else: + pass + except ImageSizeError: + print("error creating size") |