Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support to define THUMBNAIL_OPTIONS_DICT on per model basis #4

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file modified .gitignore
100644 → 100755
Empty file.
Empty file modified LICENSE
100644 → 100755
Empty file.
10 changes: 9 additions & 1 deletion README.md
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ In your `settings.py` add an option called `THUMBNAIL_OPTIONS_DICT`, defining al
}
}

Or you can also define class variable `THUMBNAIL_OPTIONS_DICT` in the model for thumbnails on model basis (see example below). This takes precedence over global settings.

In your models, use `thumbnail.models.AsyncThumbnailMixin` as a baseclass. Make sure that your model inherits
from AsyncThumbnailMixin first. This will call celery task on save(), and create one or more thumbnails
from the specified image field. Use class variable `image_field_name` to configure the field that
Expand All @@ -51,8 +53,14 @@ Example:

class Book(AsyncThumbnailMixin, models.Model):
image_field_name = 'cover_image'
THUMBNAIL_OPTIONS_DICT = {
'small': {
'geometry': '140x140',
'crop': 'center'
}
}

title = models.CharField(blank=False, max_length=255, db_index=True)
title = models.CharField(blank=False, max_length=255, db_index=True)
cover_image = thumbnail.ImageField(upload_to='books/')

In templates:
Expand Down
Empty file modified setup.py
100644 → 100755
Empty file.
5 changes: 3 additions & 2 deletions thumbnail/__init__.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ def get_thumbnail(file_, name):
"""
get_thumbnail version that uses aliasses defined in THUMBNAIL_OPTIONS_DICT
"""
options = settings.OPTIONS_DICT[name]
options_dict = getattr(file_.instance, 'THUMBNAIL_OPTIONS_DICT', settings.OPTIONS_DICT)
options = options_dict[name]
opt = copy(options)
geometry = opt.pop('geometry')

return original_get_thumbnail(file_, geometry, **opt)
return original_get_thumbnail(file_, geometry, **opt)
Empty file modified thumbnail/backend.py
100644 → 100755
Empty file.
Empty file modified thumbnail/conf/__init__.py
100644 → 100755
Empty file.
3 changes: 2 additions & 1 deletion thumbnail/conf/settings.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@
'crop': 'center'
}
}
OPTIONS_DICT = getattr(settings, 'THUMBNAIL_OPTIONS_DICT', DEFAULT_OPTIONS_DICT)
OPTIONS_DICT = getattr(settings, 'THUMBNAIL_OPTIONS_DICT', DEFAULT_OPTIONS_DICT)
SAVE_MODEL = getattr(settings, 'THUMBNAIL_SAVE_MODEL', True)
9 changes: 6 additions & 3 deletions thumbnail/models.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ class AsyncThumbnailMixin(object):
image_field_name = 'picture'

def call_upload_task(self):
for name, options in settings.OPTIONS_DICT.items():
options_dict = getattr(self, 'THUMBNAIL_OPTIONS_DICT', settings.OPTIONS_DICT)
for name, options in options_dict.items():
opt = copy(options)
geometry = opt.pop('geometry')
create_thumbnail.delay(getattr(self, self.image_field_name), geometry, **opt)
create_thumbnail.delay(self, getattr(self, self.image_field_name), geometry, **opt)

def save(self, *args, **kwargs):
thumbnail_task_completed = kwargs.pop('thumbnail_task_completed', False)
super(AsyncThumbnailMixin, self).save(*args, **kwargs)
self.call_upload_task()
if not thumbnail_task_completed:
self.call_upload_task()
24 changes: 7 additions & 17 deletions thumbnail/tasks.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,23 +1,13 @@
import celery

from sorl.thumbnail import default
from sorl.thumbnail.images import ImageFile

@celery.task
def create_thumbnail(image_file, geometry_string, **options):
# Note that thumbnail options must be same for a type of thumbnail.
# Otherwise, different thumbnails are created.
source = ImageFile(image_file)
for key, value in default.backend.default_options.items():
options.setdefault(key, value)
name = default.backend._get_thumbnail_filename(source, geometry_string, options)
thumbnail = ImageFile(name, default.storage)
source_image = default.engine.get_image(source)
default.backend._create_thumbnail(source_image, geometry_string, options, thumbnail)
from .conf import settings

# Need to set size to store in kvstore.
size = default.engine.get_image_size(source_image)
source.set_size(size)

default.kvstore.get_or_set(source)
default.kvstore.set(thumbnail, source)
@celery.task
def create_thumbnail(model, image_file, geometry_string, **options):
# Simply call get_thumbnail, if thumbnail does not exist sorl will create it
default.backend.get_thumbnail(image_file, geometry_string, **options)
if settings.SAVE_MODEL:
model.save(thumbnail_task_completed=True) # helful for signaling haystack to update index
Empty file modified thumbnail/templatetags/__init__.py
100644 → 100755
Empty file.
20 changes: 15 additions & 5 deletions thumbnail/templatetags/thumbnail_tags.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,37 @@ class CustomThumbnailNode(ThumbnailNode):
""" Extends ThumbnailNode to use thumbnail sizes from settings"""
error_message = ('Please enter sizes defined in settings')
def __init__(self, parser, token):
self.parser = parser
self.token = token
ThumbnailNode.__init__(self, parser, token)
bits = token.split_contents()

def pre_render(self, context):
file_ = self.file_.resolve(context)
bits = self.token.split_contents()
if len(bits) < 5 or bits[-2] != 'as':
raise TemplateSyntaxError(self.error_msg)
try:
thumbnail_settings = get_thumbnail_options_from_dict(settings.OPTIONS_DICT)
thumbnail_settings = get_thumbnail_options_from_dict(
getattr(file_.instance, 'THUMBNAIL_OPTIONS_DICT', settings.OPTIONS_DICT))
thumbnail_options = thumbnail_settings[bits[2]]
thumbnail_options = thumbnail_options.split()
except KeyError:
raise TemplateSyntaxError(self.error_message)
self.geometry = parser.compile_filter("'%s'" % thumbnail_options[0])
self.geometry = self.parser.compile_filter("'%s'" % thumbnail_options[0])
self.options = []
try:
m = kw_pat.match(thumbnail_options[1])
key = smart_str(m.group('key'))
expr = parser.compile_filter('"%s"' % m.group('value'))
expr = self.parser.compile_filter('"%s"' % m.group('value'))
self.options.append((key, expr))
except IndexError:
pass
self.as_var = bits[-1]

def _render(self, context):
self.pre_render(context)
return ThumbnailNode._render(self, context)

@register.tag
def thumbnail(parser, token):
return CustomThumbnailNode(parser, token)
return CustomThumbnailNode(parser, token)
Empty file modified thumbnail/utils.py
100644 → 100755
Empty file.