diff --git a/README.rst b/README.rst index bdfed79..28c42dd 100644 --- a/README.rst +++ b/README.rst @@ -277,8 +277,8 @@ with the id "imagekit:thumbnail" which, by default, is Second, we're passing two positional arguments (the dimensions and the source image) as opposed to the keyword arguments we used with the generateimage tag. -Like with the generatethumbnail tag, you can also specify additional HTML -attributes for the thumbnail tag, or use it as an assignment tag: +Like with the generateimage tag, you can also specify additional HTML attributes +for the thumbnail tag, or use it as an assignment tag: .. code-block:: html diff --git a/imagekit/cachefiles/backends.py b/imagekit/cachefiles/backends.py index b127430..a781dc7 100644 --- a/imagekit/cachefiles/backends.py +++ b/imagekit/cachefiles/backends.py @@ -17,7 +17,7 @@ def get_default_cachefile_backend(): """ from django.conf import settings return get_singleton(settings.IMAGEKIT_DEFAULT_CACHEFILE_BACKEND, - 'file backend') + 'file backend') class InvalidFileBackendError(ImproperlyConfigured): @@ -116,32 +116,78 @@ def _generate_file(backend, file, force=False): backend.generate_now(file, force=force) -try: - import celery -except ImportError: - pass -else: - _generate_file = celery.task(ignore_result=True)(_generate_file) - - -class Async(Simple): +class BaseAsync(Simple): """ - A backend that uses Celery to generate the images. + Base class for cache file backends that generate files asynchronously. """ - - def __init__(self, *args, **kwargs): - try: - import celery - except ImportError: - raise ImproperlyConfigured('You must install celery to use' - ' imagekit.cachefiles.backend.Async.') - super(Async, self).__init__(*args, **kwargs) - def generate(self, file, force=False): # Schedule the file for generation, unless we know for sure we don't # need to. If an already-generated file sneaks through, that's okay; # ``generate_now`` will catch it. We just want to make sure we don't # schedule anything we know is unnecessary--but we also don't want to # force a costly existence check. - if self.get_state(file, check_if_unknown=False) not in (CacheFileState.GENERATING, CacheFileState.EXISTS): - _generate_file.delay(self, file, force=force) + state = self.get_state(file, check_if_unknown=False) + if state not in (CacheFileState.GENERATING, CacheFileState.EXISTS): + self.schedule_generation(file, force=force) + + def schedule_generation(self, file, force=False): + # overwrite this to have the file generated in the background, + # e. g. in a worker queue. + raise NotImplementedError + + +try: + from celery import task +except ImportError: + pass +else: + _celery_task = task(ignore_result=True)(_generate_file) + + +class Celery(BaseAsync): + """ + A backend that uses Celery to generate the images. + """ + def __init__(self, *args, **kwargs): + try: + import celery + except ImportError: + raise ImproperlyConfigured('You must install celery to use' + ' imagekit.cachefiles.backends.Celery.') + super(Celery, self).__init__(*args, **kwargs) + + def schedule_generation(self, file, force=False): + _celery_task.delay(self, file, force=force) + + +Async = Celery # backwards compatibility + + +try: + import django_rq +except ImportError: + pass + + +class RQ(BaseAsync): + """ + A backend that uses RQ to generate the images. + """ + queue_name = 'default' + + def __init__(self, *args, **kwargs): + try: + import django_rq + except ImportError: + raise ImproperlyConfigured('You must install django_rq to use' + ' imagekit.cachefiles.backends.RQ.') + super(RQ, self).__init__(*args, **kwargs) + + def get_queue(self): + # not caching property to avoid "can't pickle instancemethod objects", + # see https://github.com/nvie/rq/issues/189 + return django_rq.get_queue(self.queue_name) + + def schedule_generation(self, file, force=False): + self.get_queue().enqueue(_generate_file, args=(self, file), + kwargs=dict(force=force), result_ttl=0) diff --git a/imagekit/pkgmeta.py b/imagekit/pkgmeta.py index c530bc2..caeb043 100644 --- a/imagekit/pkgmeta.py +++ b/imagekit/pkgmeta.py @@ -1,5 +1,5 @@ __title__ = 'django-imagekit' -__author__ = 'Justin Driscoll, Bryan Veloso, Greg Newman, Chris Drackett, Matthew Tretter, Eric Eldredge' -__version__ = '3.0.4' +__author__ = 'Matthew Tretter, Eric Eldredge, Bryan Veloso, Greg Newman, Chris Drackett, Justin Driscoll' +__version__ = '3.1' __license__ = 'BSD' __all__ = ['__title__', '__author__', '__version__', '__license__']