import hashlib import os from random import random import time from django.db import models from django.template.defaultfilters import filesizeformat from boards import thumbs import boards from boards.models.base import Viewable __author__ = 'neko259' IMAGE_THUMB_SIZE = (200, 150) IMAGES_DIRECTORY = 'images/' FILE_EXTENSION_DELIMITER = '.' HASH_LENGTH = 36 CSS_CLASS_IMAGE = 'image' CSS_CLASS_THUMB = 'thumb' class PostImageManager(models.Manager): def create_with_hash(self, image): image_hash = self.get_hash(image) existing = self.filter(hash=image_hash) if len(existing) > 0: post_image = existing[0] else: post_image = PostImage.objects.create(image=image) return post_image def get_hash(self, image): """ Gets hash of an image. """ md5 = hashlib.md5() for chunk in image.chunks(): md5.update(chunk) return md5.hexdigest() def get_random_images(self, count): return self.order_by('?')[:count] class PostImage(models.Model, Viewable): objects = PostImageManager() class Meta: app_label = 'boards' ordering = ('id',) def _update_image_filename(self, filename): """ Gets unique image filename """ path = IMAGES_DIRECTORY # TODO Use something other than random number in file name new_name = '{}{}.{}'.format( str(int(time.mktime(time.gmtime()))), str(int(random() * 1000)), filename.split(FILE_EXTENSION_DELIMITER)[-1:][0]) return os.path.join(path, new_name) width = models.IntegerField(default=0) height = models.IntegerField(default=0) pre_width = models.IntegerField(default=0) pre_height = models.IntegerField(default=0) image = thumbs.ImageWithThumbsField(upload_to=_update_image_filename, blank=True, sizes=(IMAGE_THUMB_SIZE,), width_field='width', height_field='height', preview_width_field='pre_width', preview_height_field='pre_height') hash = models.CharField(max_length=HASH_LENGTH) def save(self, *args, **kwargs): """ Saves the model and computes the image hash for deduplication purposes. """ if not self.pk and self.image: self.hash = PostImage.objects.get_hash(self.image) super(PostImage, self).save(*args, **kwargs) def __str__(self): return self.image.url def get_view(self): metadata = '{}, {}'.format(self.image.name.split('.')[-1], filesizeformat(self.image.size)) return '
' \ '' \ '{}' \ '' \ '
{image_meta}
' \ '
'\ .format(CSS_CLASS_IMAGE, CSS_CLASS_THUMB, self.image.url_200x150, str(self.hash), str(self.pre_width), str(self.pre_height), str(self.width), str(self.height), full=self.image.url, image_meta=metadata) def get_random_associated_post(self): return boards.models.Post.objects.filter(images__in=[self])\ .order_by('?').first()