class Video(Media): """ A local or remote video file """ file = models.FileField(upload_to=custom_upload_to( appsettings.VIDEO_UPLOAD_TO), blank=True, null=True, storage=VIDEO_STORAGE()) thumbnail = models.ForeignKey(Image, null=True, blank=True) def thumb(self): if self.thumbnail: return self.thumbnail.thumb() else: return '' thumb.allow_tags = True thumb.short_description = _("Thumbnail") @property def media_url(self): return self.external_url or self.file.url def parse_metadata(self): super(Video, self).parse_metadata() self.width = self.metadata['Image width'] self.height = self.metadata['Image height']
class Document(Media): """ A generic file """ file = models.FileField(upload_to=custom_upload_to( appsettings.DOC_UPLOAD_TO), blank=True, null=True, storage=DOC_STORAGE()) class Meta: verbose_name = _("Document") verbose_name_plural = _("Documents") @property def media_url(self): return self.external_url or self.file.url
class Flash(Media): """ A flash SWF file to be played in a custom player """ file = models.FileField(upload_to=custom_upload_to( appsettings.FLASH_UPLOAD_TO), blank=True, null=True, storage=FLASH_STORAGE()) class Meta: verbose_name = _("SWF File") verbose_name_plural = _("SWF Files") @property def media_url(self): return self.external_url or self.file.url
class Audio(Media): """ An audio file """ file = models.FileField(upload_to=custom_upload_to( appsettings.AUDIO_UPLOAD_TO), blank=True, null=True, storage=AUDIO_STORAGE()) class Meta: verbose_name = _("audio clip") verbose_name_plural = _("audio clips") @property def media_url(self): return self.external_url or self.file.url
class Image(Media): """ We are using a File field instead of Image field because the Image field will cause a problem if the file doesn't exist and you merely access the record. """ file = models.FileField(upload_to=custom_upload_to( appsettings.IMAGE_UPLOAD_TO), blank=True, null=True, storage=IMAGE_STORAGE()) thumbnail = models.ImageField(upload_to=custom_upload_to( appsettings.THUMB_UPLOAD_TO), blank=True, null=True, width_field='thumb_width', height_field='thumb_height', editable=False, storage=IMAGE_STORAGE()) thumb_width = models.IntegerField(blank=True, null=True, editable=False) thumb_height = models.IntegerField(blank=True, null=True, editable=False) original = models.ForeignKey('self', related_name="variations", blank=True, null=True) def save(self, *args, **kwargs): generate_thumb = self.id is None super(Image, self).save(*args, **kwargs) if generate_thumb: self._generate_thumbnail() def _generate_thumbnail(self): if self.file: image = PilImage.open(self.file.path) filename = os.path.basename(self.file.name) elif self.external_url: import urllib filepath, headers = urllib.urlretrieve(self.external_url) image = PilImage.open(filepath) filename = os.path.basename(filepath) if image.mode not in ('L', 'RGB'): image = image.convert('RGB') image.thumbnail(appsettings.THUMB_SIZE, PilImage.ANTIALIAS) destination = StringIO() image.save(destination, format='JPEG') destination.seek(0) self.thumbnail.save(filename, ContentFile(destination.read())) def smart_fit(self, width=20000, height=20000): """ Given a width, height or both, it will return the width and height to fit in the given area. """ im_width = self.width im_height = self.height if width == 20000 and height == 20000: return im_width, im_height elif width is None: width = 20000 elif height is None: height = 20000 if width < height: scale = float(width) / float(im_width) height = int(round(scale * im_height)) else: scale = float(height) / float(im_height) width = int(round(scale * im_width)) return width, height @property def media_url(self): return self.external_url or self.file.url def _get_raw_metadata(self, path): data = super(Image, self)._get_raw_metadata(path) if HAS_IPTC: try: data.update(IPTCInfo(path).__dict__['_data']) except: pass return data def parse_metadata(self): super(Image, self).parse_metadata() self.width = self.metadata['Image width'] self.height = self.metadata['Image height'] self.one_off_author = self.metadata['Author'] or self.metadata[ '80'] or '' if isinstance(self.one_off_author, (tuple, list)): self.one_off_author = ", ".join(self.one_off_author) if not self.caption: self.caption = self.metadata['120'] or self.metadata['Title'] or '' tags = [] tags.extend(self.metadata["15"] or []) tags.extend(self.metadata["20"] or []) tags.extend(self.metadata["25"] or []) categories = ", ".join([x[:50] for x in tags]) self.categories = super_force_ascii(categories)