image.py
121 lines
| 3.8 KiB
| text/x-python
|
PythonLexer
|
r693 | import hashlib | ||
import os | ||||
from random import random | ||||
import time | ||||
|
r1249 | |||
|
r693 | from django.db import models | ||
|
r1245 | from django.template.defaultfilters import filesizeformat | ||
|
r1249 | |||
|
r693 | from boards import thumbs | ||
|
r1249 | import boards | ||
|
r931 | from boards.models.base import Viewable | ||
|
r693 | |||
__author__ = 'neko259' | ||||
IMAGE_THUMB_SIZE = (200, 150) | ||||
IMAGES_DIRECTORY = 'images/' | ||||
FILE_EXTENSION_DELIMITER = '.' | ||||
|
r931 | HASH_LENGTH = 36 | ||
CSS_CLASS_IMAGE = 'image' | ||||
CSS_CLASS_THUMB = 'thumb' | ||||
|
r693 | |||
|
r1025 | class PostImageManager(models.Manager): | ||
def create_with_hash(self, image): | ||||
|
r1027 | image_hash = self.get_hash(image) | ||
|
r1025 | 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 | ||||
|
r1027 | def get_hash(self, image): | ||
""" | ||||
Gets hash of an image. | ||||
""" | ||||
md5 = hashlib.md5() | ||||
for chunk in image.chunks(): | ||||
md5.update(chunk) | ||||
return md5.hexdigest() | ||||
|
r1252 | def get_random_images(self, count, include_archived=False, tags=None): | ||
images = self.filter(post_images__thread__archived=include_archived) | ||||
if tags is not None: | ||||
|
r1263 | images = images.filter(post_images__threads__tags__in=tags) | ||
|
r1252 | return images.order_by('?')[:count] | ||
|
r1249 | |||
|
r1025 | |||
|
r931 | class PostImage(models.Model, Viewable): | ||
|
r1025 | objects = PostImageManager() | ||
|
r693 | class Meta: | ||
app_label = 'boards' | ||||
ordering = ('id',) | ||||
|
r714 | def _update_image_filename(self, filename): | ||
|
r693 | """ | ||
Gets unique image filename | ||||
""" | ||||
|
r1025 | # TODO Use something other than random number in file name | ||
new_name = '{}{}.{}'.format( | ||||
|
r1027 | str(int(time.mktime(time.gmtime()))), | ||
str(int(random() * 1000)), | ||||
filename.split(FILE_EXTENSION_DELIMITER)[-1:][0]) | ||||
|
r693 | |||
|
r1273 | return os.path.join(IMAGES_DIRECTORY, new_name) | ||
|
r693 | |||
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') | ||||
|
r931 | hash = models.CharField(max_length=HASH_LENGTH) | ||
|
r693 | |||
def save(self, *args, **kwargs): | ||||
""" | ||||
Saves the model and computes the image hash for deduplication purposes. | ||||
""" | ||||
if not self.pk and self.image: | ||||
|
r1027 | self.hash = PostImage.objects.get_hash(self.image) | ||
|
r693 | super(PostImage, self).save(*args, **kwargs) | ||
|
r812 | def __str__(self): | ||
return self.image.url | ||||
|
r931 | def get_view(self): | ||
|
r1245 | metadata = '{}, {}'.format(self.image.name.split('.')[-1], | ||
filesizeformat(self.image.size)) | ||||
|
r931 | return '<div class="{}">' \ | ||
|
r1122 | '<a class="{}" href="{full}">' \ | ||
'<img class="post-image-preview"' \ | ||||
|
r931 | ' src="{}"' \ | ||
' alt="{}"' \ | ||||
' width="{}"' \ | ||||
' height="{}"' \ | ||||
' data-width="{}"' \ | ||||
' data-height="{}" />' \ | ||||
'</a>' \ | ||||
|
r1245 | '<div class="image-metadata">{image_meta}</div>' \ | ||
|
r931 | '</div>'\ | ||
|
r1122 | .format(CSS_CLASS_IMAGE, CSS_CLASS_THUMB, | ||
|
r931 | self.image.url_200x150, | ||
str(self.hash), str(self.pre_width), | ||||
|
r1245 | str(self.pre_height), str(self.width), str(self.height), | ||
full=self.image.url, image_meta=metadata) | ||||
|
r1249 | |||
|
r1264 | def get_random_associated_post(self): | ||
|
r1263 | posts = boards.models.Post.objects.filter(images__in=[self]) | ||
return posts.order_by('?').first() | ||||