+++ /dev/null
-from UserDict import DictMixin
-try:
- from cStringIO import StringIO
-except ImportError:
- from StringIO import StringIO
-
-from django.db.models.fields.files import ImageField, ImageFieldFile
-from django.core.files.base import ContentFile
-from django.utils.safestring import mark_safe
-from django.utils.html import escape
-
-from sorl.thumbnail.base import Thumbnail
-from sorl.thumbnail.main import DjangoThumbnail, build_thumbnail_name
-from sorl.thumbnail.utils import delete_thumbnails
-
-
-REQUIRED_ARGS = ('size',)
-ALL_ARGS = {
- 'size': 'requested_size',
- 'options': 'opts',
- 'quality': 'quality',
- 'basedir': 'basedir',
- 'subdir': 'subdir',
- 'prefix': 'prefix',
- 'extension': 'extension',
-}
-BASE_ARGS = {
- 'size': 'requested_size',
- 'options': 'opts',
- 'quality': 'quality',
-}
-TAG_HTML = '<img src="%(src)s" width="%(width)s" height="%(height)s" alt="" />'
-
-
-class ThumbsDict(object, DictMixin):
- def __init__(self, descriptor):
- super(ThumbsDict, self).__init__()
- self.descriptor = descriptor
-
- def keys(self):
- return self.descriptor.field.extra_thumbnails.keys()
-
-
-class LazyThumbs(ThumbsDict):
- def __init__(self, *args, **kwargs):
- super(LazyThumbs, self).__init__(*args, **kwargs)
- self.cached = {}
-
- def __getitem__(self, key):
- thumb = self.cached.get(key)
- if not thumb:
- args = self.descriptor.field.extra_thumbnails[key]
- thumb = self.descriptor._build_thumbnail(args)
- self.cached[key] = thumb
- return thumb
-
- def keys(self):
- return self.descriptor.field.extra_thumbnails.keys()
-
-
-class ThumbTags(ThumbsDict):
- def __getitem__(self, key):
- thumb = self.descriptor.extra_thumbnails[key]
- return self.descriptor._build_thumbnail_tag(thumb)
-
-
-class BaseThumbnailFieldFile(ImageFieldFile):
- def _build_thumbnail(self, args):
- # Build the DjangoThumbnail kwargs.
- kwargs = {}
- for k, v in args.items():
- kwargs[ALL_ARGS[k]] = v
- # Build the destination filename and return the thumbnail.
- name_kwargs = {}
- for key in ['size', 'options', 'quality', 'basedir', 'subdir',
- 'prefix', 'extension']:
- name_kwargs[key] = args.get(key)
- source = getattr(self.instance, self.field.name)
- dest = build_thumbnail_name(source.name, **name_kwargs)
- return DjangoThumbnail(source, relative_dest=dest, **kwargs)
-
- def _build_thumbnail_tag(self, thumb):
- opts = dict(src=escape(thumb), width=thumb.width(),
- height=thumb.height())
- return mark_safe(self.field.thumbnail_tag % opts)
-
- def _get_extra_thumbnails(self):
- if self.field.extra_thumbnails is None:
- return None
- if not hasattr(self, '_extra_thumbnails'):
- self._extra_thumbnails = LazyThumbs(self)
- return self._extra_thumbnails
- extra_thumbnails = property(_get_extra_thumbnails)
-
- def _get_extra_thumbnails_tag(self):
- if self.field.extra_thumbnails is None:
- return None
- return ThumbTags(self)
- extra_thumbnails_tag = property(_get_extra_thumbnails_tag)
-
- def save(self, *args, **kwargs):
- # Optionally generate the thumbnails after the image is saved.
- super(BaseThumbnailFieldFile, self).save(*args, **kwargs)
- if self.field.generate_on_save:
- self.generate_thumbnails()
-
- def delete(self, *args, **kwargs):
- # Delete any thumbnails too (and not just ones defined here in case
- # the {% thumbnail %} tag was used or the thumbnail sizes changed).
- relative_source_path = getattr(self.instance, self.field.name).name
- delete_thumbnails(relative_source_path)
- super(BaseThumbnailFieldFile, self).delete(*args, **kwargs)
-
- def generate_thumbnails(self):
- # Getting the thumbs generates them.
- if self.extra_thumbnails:
- self.extra_thumbnails.values()
-
-
-class ImageWithThumbnailsFieldFile(BaseThumbnailFieldFile):
- def _get_thumbnail(self):
- return self._build_thumbnail(self.field.thumbnail)
- thumbnail = property(_get_thumbnail)
-
- def _get_thumbnail_tag(self):
- return self._build_thumbnail_tag(self.thumbnail)
- thumbnail_tag = property(_get_thumbnail_tag)
-
- def generate_thumbnails(self, *args, **kwargs):
- self.thumbnail.generate()
- Super = super(ImageWithThumbnailsFieldFile, self)
- return Super.generate_thumbnails(*args, **kwargs)
-
-
-class ThumbnailFieldFile(BaseThumbnailFieldFile):
- def save(self, name, content, *args, **kwargs):
- new_content = StringIO()
- # Build the Thumbnail kwargs.
- thumbnail_kwargs = {}
- for k, argk in BASE_ARGS.items():
- if not k in self.field.thumbnail:
- continue
- thumbnail_kwargs[argk] = self.field.thumbnail[k]
- Thumbnail(source=content, dest=new_content, **thumbnail_kwargs)
- new_content = ContentFile(new_content.read())
- super(ThumbnailFieldFile, self).save(name, new_content, *args,
- **kwargs)
-
- def _get_thumbnail_tag(self):
- opts = dict(src=escape(self.url), width=self.width,
- height=self.height)
- return mark_safe(self.field.thumbnail_tag % opts)
- thumbnail_tag = property(_get_thumbnail_tag)
-
-
-class BaseThumbnailField(ImageField):
- def __init__(self, *args, **kwargs):
- # The new arguments for this field aren't explicitly defined so that
- # users can still use normal ImageField positional arguments.
- self.extra_thumbnails = kwargs.pop('extra_thumbnails', None)
- self.thumbnail_tag = kwargs.pop('thumbnail_tag', TAG_HTML)
- self.generate_on_save = kwargs.pop('generate_on_save', False)
-
- super(BaseThumbnailField, self).__init__(*args, **kwargs)
- _verify_thumbnail_attrs(self.thumbnail)
- if self.extra_thumbnails:
- for extra, attrs in self.extra_thumbnails.items():
- name = "%r of 'extra_thumbnails'"
- _verify_thumbnail_attrs(attrs, name)
-
- def south_field_triple(self):
- """
- Return a suitable description of this field for South.
- """
- # We'll just introspect ourselves, since we inherit.
- from south.modelsinspector import introspector
- field_class = "django.db.models.fields.files.ImageField"
- args, kwargs = introspector(self)
- # That's our definition!
- return (field_class, args, kwargs)
-
-
-class ImageWithThumbnailsField(BaseThumbnailField):
- """
- photo = ImageWithThumbnailsField(
- upload_to='uploads',
- thumbnail={'size': (80, 80), 'options': ('crop', 'upscale'),
- 'extension': 'png'},
- extra_thumbnails={
- 'admin': {'size': (70, 50), 'options': ('sharpen',)},
- }
- )
- """
- attr_class = ImageWithThumbnailsFieldFile
-
- def __init__(self, *args, **kwargs):
- self.thumbnail = kwargs.pop('thumbnail', None)
- super(ImageWithThumbnailsField, self).__init__(*args, **kwargs)
-
-
-class ThumbnailField(BaseThumbnailField):
- """
- avatar = ThumbnailField(
- upload_to='uploads',
- size=(200, 200),
- options=('crop',),
- extra_thumbnails={
- 'admin': {'size': (70, 50), 'options': (crop, 'sharpen')},
- }
- )
- """
- attr_class = ThumbnailFieldFile
-
- def __init__(self, *args, **kwargs):
- self.thumbnail = {}
- for attr in ALL_ARGS:
- if attr in kwargs:
- self.thumbnail[attr] = kwargs.pop(attr)
- super(ThumbnailField, self).__init__(*args, **kwargs)
-
-
-def _verify_thumbnail_attrs(attrs, name="'thumbnail'"):
- for arg in REQUIRED_ARGS:
- if arg not in attrs:
- raise TypeError('Required attr %r missing in %s arg' % (arg, name))
- for attr in attrs:
- if attr not in ALL_ARGS:
- raise TypeError('Invalid attr %r found in %s arg' % (arg, name))