image.py
105 lines
| 3.1 KiB
| text/x-python
|
PythonLexer
neko259
|
r693 | import hashlib | ||
import os | ||||
from random import random | ||||
import time | ||||
from django.db import models | ||||
from boards import thumbs | ||||
neko259
|
r931 | from boards.models.base import Viewable | ||
neko259
|
r693 | |||
__author__ = 'neko259' | ||||
IMAGE_THUMB_SIZE = (200, 150) | ||||
IMAGES_DIRECTORY = 'images/' | ||||
FILE_EXTENSION_DELIMITER = '.' | ||||
neko259
|
r931 | HASH_LENGTH = 36 | ||
CSS_CLASS_IMAGE = 'image' | ||||
CSS_CLASS_THUMB = 'thumb' | ||||
neko259
|
r693 | |||
neko259
|
r1025 | class PostImageManager(models.Manager): | ||
def create_with_hash(self, image): | ||||
neko259
|
r1027 | image_hash = self.get_hash(image) | ||
neko259
|
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 | ||||
neko259
|
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() | ||||
neko259
|
r1025 | |||
neko259
|
r931 | class PostImage(models.Model, Viewable): | ||
neko259
|
r1025 | objects = PostImageManager() | ||
neko259
|
r693 | class Meta: | ||
app_label = 'boards' | ||||
ordering = ('id',) | ||||
neko259
|
r714 | def _update_image_filename(self, filename): | ||
neko259
|
r693 | """ | ||
Gets unique image filename | ||||
""" | ||||
path = IMAGES_DIRECTORY | ||||
neko259
|
r1025 | |||
# TODO Use something other than random number in file name | ||||
new_name = '{}{}.{}'.format( | ||||
neko259
|
r1027 | str(int(time.mktime(time.gmtime()))), | ||
str(int(random() * 1000)), | ||||
filename.split(FILE_EXTENSION_DELIMITER)[-1:][0]) | ||||
neko259
|
r693 | |||
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') | ||||
neko259
|
r931 | hash = models.CharField(max_length=HASH_LENGTH) | ||
neko259
|
r693 | |||
def save(self, *args, **kwargs): | ||||
""" | ||||
Saves the model and computes the image hash for deduplication purposes. | ||||
""" | ||||
if not self.pk and self.image: | ||||
neko259
|
r1027 | self.hash = PostImage.objects.get_hash(self.image) | ||
neko259
|
r693 | super(PostImage, self).save(*args, **kwargs) | ||
neko259
|
r812 | def __str__(self): | ||
return self.image.url | ||||
neko259
|
r931 | def get_view(self): | ||
return '<div class="{}">' \ | ||||
neko259
|
r1122 | '<a class="{}" href="{full}">' \ | ||
'<img class="post-image-preview"' \ | ||||
neko259
|
r931 | ' src="{}"' \ | ||
' alt="{}"' \ | ||||
' width="{}"' \ | ||||
' height="{}"' \ | ||||
' data-width="{}"' \ | ||||
' data-height="{}" />' \ | ||||
'</a>' \ | ||||
'</div>'\ | ||||
neko259
|
r1122 | .format(CSS_CLASS_IMAGE, CSS_CLASS_THUMB, | ||
neko259
|
r931 | self.image.url_200x150, | ||
str(self.hash), str(self.pre_width), | ||||
neko259
|
r1122 | str(self.pre_height), str(self.width), str(self.height), full=self.image.url) | ||