import boards from boards.models import STATUS_ARCHIVE from django.core.files.images import get_image_dimensions from django.db import models from boards import utils from boards.models.attachment.viewers import get_viewers, AbstractViewer, \ FILE_TYPES_IMAGE from boards.utils import get_upload_filename, get_extension, cached_result class AttachmentManager(models.Manager): def create_with_hash(self, file): file_hash = utils.get_file_hash(file) existing = self.filter(hash=file_hash) if len(existing) > 0: attachment = existing[0] else: # FIXME Use full mimetype here, need to modify viewers too file_type = get_extension(file.name) attachment = self.create(file=file, mimetype=file_type, hash=file_hash) return attachment def get_random_images(self, count, tags=None): images = self.filter(mimetype__in=FILE_TYPES_IMAGE).exclude( attachment_posts__thread__status=STATUS_ARCHIVE) if tags is not None: images = images.filter(attachment_posts__threads__tags__in=tags) return images.order_by('?')[:count] class Attachment(models.Model): objects = AttachmentManager() file = models.FileField(upload_to=get_upload_filename) mimetype = models.CharField(max_length=50) hash = models.CharField(max_length=36) alias = models.TextField(unique=True, null=True, blank=True) def get_view(self): file_viewer = None for viewer in get_viewers(): if viewer.supports(self.mimetype): file_viewer = viewer break if file_viewer is None: file_viewer = AbstractViewer return file_viewer(self.file, self.mimetype, self.hash).get_view() def __str__(self): return self.file.url def get_random_associated_post(self): posts = boards.models.Post.objects.filter(attachments__in=[self]) return posts.order_by('?').first() @cached_result() def get_size(self): if self.mimetype in FILE_TYPES_IMAGE: return get_image_dimensions(self.file) else: return 200, 150 def get_thumb_url(self): split = self.file.url.rsplit('.', 1) w, h = 200, 150 return '%s.%sx%s.%s' % (split[0], w, h, split[1]) @cached_result() def get_preview_size(self): if self.mimetype in FILE_TYPES_IMAGE: preview_path = self.file.path.replace('.', '.200x150.') return get_image_dimensions(preview_path) else: return 200, 150