3 from django.conf import settings
4 from django.utils.encoding import iri_to_uri, force_unicode
6 from sorl.thumbnail.base import Thumbnail
7 from sorl.thumbnail.processors import dynamic_import
8 from sorl.thumbnail import defaults
11 def get_thumbnail_setting(setting, override=None):
13 Get a thumbnail setting from Django settings module, falling back to the
16 If override is not None, it will be used instead of the setting.
18 if override is not None:
20 if hasattr(settings, 'THUMBNAIL_%s' % setting):
21 return getattr(settings, 'THUMBNAIL_%s' % setting)
23 return getattr(defaults, setting)
26 def build_thumbnail_name(source_name, size, options=None,
27 quality=None, basedir=None, subdir=None, prefix=None,
29 quality = get_thumbnail_setting('QUALITY', quality)
30 basedir = get_thumbnail_setting('BASEDIR', basedir)
31 subdir = get_thumbnail_setting('SUBDIR', subdir)
32 prefix = get_thumbnail_setting('PREFIX', prefix)
33 extension = get_thumbnail_setting('EXTENSION', extension)
34 path, filename = os.path.split(source_name)
35 basename, ext = os.path.splitext(filename)
36 name = '%s%s' % (basename, ext.replace(os.extsep, '_'))
37 size = '%sx%s' % tuple(size)
39 # Handle old list format for opts.
40 options = options or {}
41 if isinstance(options, (list, tuple)):
42 options = dict([(opt, None) for opt in options])
44 opts = options.items()
45 opts.sort() # options are sorted so the filename is consistent
46 opts = ['%s_' % (v is not None and '%s-%s' % (k, v) or k)
49 extension = extension and '.%s' % extension
50 thumbnail_filename = '%s%s_%s_%sq%s%s' % (prefix, name, size, opts,
52 return os.path.join(basedir, path, subdir, thumbnail_filename)
55 class DjangoThumbnail(Thumbnail):
56 imagemagick_file_types = get_thumbnail_setting('IMAGEMAGICK_FILE_TYPES')
58 def __init__(self, relative_source, requested_size, opts=None,
59 quality=None, basedir=None, subdir=None, prefix=None,
60 relative_dest=None, processors=None, extension=None):
61 relative_source = force_unicode(relative_source)
62 # Set the absolute filename for the source file
63 source = self._absolute_path(relative_source)
65 quality = get_thumbnail_setting('QUALITY', quality)
66 convert_path = get_thumbnail_setting('CONVERT')
67 wvps_path = get_thumbnail_setting('WVPS')
68 if processors is None:
69 processors = dynamic_import(get_thumbnail_setting('PROCESSORS'))
71 # Call super().__init__ now to set the opts attribute. generate() won't
72 # get called because we are not setting the dest attribute yet.
73 super(DjangoThumbnail, self).__init__(source, requested_size,
74 opts=opts, quality=quality, convert_path=convert_path,
75 wvps_path=wvps_path, processors=processors)
77 # Get the relative filename for the thumbnail image, then set the
78 # destination filename
79 if relative_dest is None:
81 self._get_relative_thumbnail(relative_source, basedir=basedir,
82 subdir=subdir, prefix=prefix,
84 filelike = not isinstance(relative_dest, basestring)
86 self.dest = relative_dest
88 self.dest = self._absolute_path(relative_dest)
90 # Call generate now that the dest attribute has been set
93 # Set the relative & absolute url to the thumbnail
96 iri_to_uri('/'.join(relative_dest.split(os.sep)))
97 self.absolute_url = '%s%s' % (settings.MEDIA_URL,
100 def _get_relative_thumbnail(self, relative_source,
101 basedir=None, subdir=None, prefix=None,
104 Returns the thumbnail filename including relative path.
106 return build_thumbnail_name(relative_source, self.requested_size,
107 self.opts, self.quality, basedir, subdir,
110 def _absolute_path(self, filename):
111 absolute_filename = os.path.join(settings.MEDIA_ROOT, filename)
112 return absolute_filename.encode(settings.FILE_CHARSET)
114 def __unicode__(self):
115 return self.absolute_url