mirror of
https://github.com/Hopiu/django-imagekit.git
synced 2026-04-09 07:51:00 +00:00
Let's call em cachefiles
Changed my mind about 04aa72c1f9. It's
just a better description, even if different strategies can change the
behavior so it isn't really very cache-like.
This commit is contained in:
parent
59971b6cd4
commit
301adc2087
18 changed files with 107 additions and 107 deletions
|
|
@ -62,7 +62,7 @@ your model class:
|
|||
options={'quality': 60})
|
||||
|
||||
profile = Profile.objects.all()[0]
|
||||
print profile.avatar_thumbnail.url # > /media/generated/images/982d5af84cddddfd0fbf70892b4431e4.jpg
|
||||
print profile.avatar_thumbnail.url # > /media/CACHE/images/982d5af84cddddfd0fbf70892b4431e4.jpg
|
||||
print profile.avatar_thumbnail.width # > 100
|
||||
|
||||
As you can probably tell, ImageSpecFields work a lot like Django's
|
||||
|
|
@ -221,7 +221,7 @@ This will output the following HTML:
|
|||
|
||||
.. code-block:: html
|
||||
|
||||
<img src="/media/generated/iimages/982d5af84cddddfd0fbf70892b4431e4.jpg" width="100" height="50" />
|
||||
<img src="/media/CACHE/iimages/982d5af84cddddfd0fbf70892b4431e4.jpg" width="100" height="50" />
|
||||
|
||||
You can also add additional HTML attributes; just separate them from your
|
||||
keyword args using two dashes:
|
||||
|
|
@ -259,7 +259,7 @@ Like the generateimage tag, the thumbnail tag outputs an <img> tag:
|
|||
|
||||
.. code-block:: html
|
||||
|
||||
<img src="/media/generated/iimages/982d5af84cddddfd0fbf70892b4431e4.jpg" width="100" height="50" />
|
||||
<img src="/media/CACHE/iimages/982d5af84cddddfd0fbf70892b4431e4.jpg" width="100" height="50" />
|
||||
|
||||
Comparing this syntax to the generateimage tag above, you'll notice a few
|
||||
differences.
|
||||
|
|
|
|||
|
|
@ -2,27 +2,27 @@ Unlike Django's ImageFields, ImageKit's ImageSpecFields and template tags don't
|
|||
persist any data in the database. Therefore, in order to know whether an image
|
||||
file needs to be generated, ImageKit needs to check if the file already exists
|
||||
(using the appropriate file storage object`__). The object responsible for
|
||||
performing these checks is called a *generated file backend*.
|
||||
performing these checks is called a *cache file backend*.
|
||||
|
||||
|
||||
Cache!
|
||||
------
|
||||
|
||||
By default, ImageKit checks for the existence of a generated file every time you
|
||||
By default, ImageKit checks for the existence of a cache file every time you
|
||||
attempt to use the file and, if it doesn't exist, creates it synchronously. This
|
||||
is a very safe behavior because it ensures that your ImageKit-generated images
|
||||
are always available. However, that's a lot of checking with storage and those
|
||||
kinds of operations can be slow—especially if you're using a remote storage—so
|
||||
you'll want to try to avoid them as much as possible.
|
||||
|
||||
Luckily, the default generated file backend makes use of Django's caching
|
||||
Luckily, the default cache file backend makes use of Django's caching
|
||||
abilities to mitigate the number of checks it actually has to do; it will use
|
||||
the cache specified by the ``IMAGEKIT_CACHE_BACKEND`` to save the state of the
|
||||
generated file. If your Django project is running in debug mode
|
||||
(``settings.DEBUG`` is true), this will be a dummy cache by default. Otherwise,
|
||||
it will use your project's default cache.
|
||||
|
||||
In normal operation, your generated files will never be deleted; once they're
|
||||
In normal operation, your cache files will never be deleted; once they're
|
||||
created, they'll stay created. So the simplest optimization you can make is to
|
||||
set your ``IMAGEKIT_CACHE_BACKEND`` to a cache with a very long, or infinite,
|
||||
timeout.
|
||||
|
|
@ -36,10 +36,10 @@ files—a cache with a long timeout is all the optimization you'll need. However
|
|||
there may be times when that simply doesn't cut it. In these cases, you'll want
|
||||
to change when the generation is actually done.
|
||||
|
||||
The objects responsible for specifying when generated files are created are
|
||||
called *generated file strategies*. The default strategy can be set using the
|
||||
``IMAGEKIT_DEFAULT_GENERATEDFILE_STRATEGY`` setting, and its default value is
|
||||
`'imagekit.generatedfiles.strategies.JustInTime'`. As we've already seen above,
|
||||
The objects responsible for specifying when cache files are created are
|
||||
called *cache file strategies*. The default strategy can be set using the
|
||||
``IMAGEKIT_DEFAULT_CACHEFILE_STRATEGY`` setting, and its default value is
|
||||
`'imagekit.cachefiles.strategies.JustInTime'`. As we've already seen above,
|
||||
the "just in time" strategy determines whether a file needs to be generated each
|
||||
time it's accessed and, if it does, generates it synchronously (that is, as part
|
||||
of the request-response cycle).
|
||||
|
|
@ -47,9 +47,9 @@ of the request-response cycle).
|
|||
Another strategy is to simply assume the file exists. This requires the fewest
|
||||
number of checks (zero!), so we don't have to worry about expensive IO. The
|
||||
strategy that takes this approach is
|
||||
``imagekit.generatedfiles.strategies.Optimistic``. In order to use this
|
||||
strategy, either set the ``IMAGEKIT_DEFAULT_GENERATEDFILE_STRATEGY`` setting or,
|
||||
to use it on a per-generator basis, set the ``generatedfile_strategy`` attribute
|
||||
``imagekit.cachefiles.strategies.Optimistic``. In order to use this
|
||||
strategy, either set the ``IMAGEKIT_DEFAULT_CACHEFILE_STRATEGY`` setting or,
|
||||
to use it on a per-generator basis, set the ``cachefile_strategy`` attribute
|
||||
of your spec or generator. Avoiding checking for file existence can be a real
|
||||
boon to performance, but it also means that ImageKit has no way to know when a
|
||||
file needs to be generated—well, at least not all the time.
|
||||
|
|
@ -76,7 +76,7 @@ ImageKit makes this pretty easy:
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
from imagekit.generatedfiles import LazyGeneratedImageFile
|
||||
from imagekit.cachefiles import LazyGeneratedImageFile
|
||||
|
||||
file = LazyGeneratedImageFile('myapp:profile:avatar_thumbnail', source=source_file)
|
||||
file.generate()
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ responsible for two things:
|
|||
2. They expose a generator method that enumerates source files.
|
||||
|
||||
When these objects are registered (using ``imagekit.register.source_group()``),
|
||||
their signals will trigger callbacks on the generated file strategies associated
|
||||
their signals will trigger callbacks on the cache file strategies associated
|
||||
with image specs that use the source. (So, for example, you can chose to
|
||||
generate a file every time the source image changes.) In addition, the generator
|
||||
method is used (indirectly) to create the list of files to generate with the
|
||||
|
|
@ -30,7 +30,7 @@ generator method that iterates over every Profile's "avatar" image.
|
|||
Chances are, this is the only source group you will ever need to use, however,
|
||||
ImageKit lets you define and register custom source groups easily. This may be
|
||||
useful, for example, if you're using the template tags "generateimage" and
|
||||
"thumbnail" and the optimistic generated file strategy. Again, the purpose is
|
||||
"thumbnail" and the optimistic cache file strategy. Again, the purpose is
|
||||
to tell ImageKit which specs are used with which sources (so the
|
||||
"generateimages" management command can generate those files) and when the
|
||||
source image has been created or changed (so that the strategy has the
|
||||
|
|
@ -65,5 +65,5 @@ generated (using the "myapp:profile:avatar_thumbnail" spec) for each of the
|
|||
JPEGs in `/path/to/some/pics`.
|
||||
|
||||
Note that, since this source group doesnt send the `source_created` or
|
||||
`source_changed` signals, the corresponding generated file strategy callbacks
|
||||
`source_changed` signals, the corresponding cache file strategy callbacks
|
||||
would not be called for them.
|
||||
|
|
|
|||
|
|
@ -54,16 +54,16 @@ by providing an ``image_cache_backend``:
|
|||
This gave you great control over *how* your images are generated and stored,
|
||||
but it could be difficult to control *when* they were generated and stored.
|
||||
|
||||
IK3 retains the image cache backend concept (now called generated file backends),
|
||||
but separates the 'when' control out to generated file strategies:
|
||||
IK3 retains the image cache backend concept (now called cache file backends),
|
||||
but separates the 'when' control out to cache file strategies:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class Photo(models.Model):
|
||||
...
|
||||
thumbnail = ImageSpecField(...,
|
||||
generatedfile_backend=MyGeneratedFileBackend(),
|
||||
generatedfile_strategy=MyGeneratedFileStrategy())
|
||||
cachefile_backend=MyCacheFileBackend(),
|
||||
cachefile_strategy=MyCacheFileStrategy())
|
||||
|
||||
If you are using the IK2 default image cache backend setting:
|
||||
|
||||
|
|
@ -71,18 +71,18 @@ If you are using the IK2 default image cache backend setting:
|
|||
|
||||
IMAGEKIT_DEFAULT_IMAGE_CACHE_BACKEND = 'path.to.MyImageCacheBackend'
|
||||
|
||||
IK3 provides analogous settings for generated file backends and strategies:
|
||||
IK3 provides analogous settings for cache file backends and strategies:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
IMAGEKIT_DEFAULT_GENERATEDFILE_BACKEND = 'path.to.MyGeneratedFileBackend'
|
||||
IMAGEKIT_DEFAULT_GENERATEDFILE_STRATEGY = 'path.to.MyGeneratedFileStrategy'
|
||||
IMAGEKIT_DEFAULT_CACHEFILE_BACKEND = 'path.to.MyCacheFileBackend'
|
||||
IMAGEKIT_DEFAULT_CACHEFILE_STRATEGY = 'path.to.MyCacheFileStrategy'
|
||||
|
||||
See the documentation on `generated file backends`_ and `generated file strategies`_
|
||||
See the documentation on `cache file backends`_ and `cache file strategies`_
|
||||
for more details.
|
||||
|
||||
.. _`generated file backends`:
|
||||
.. _`generated file strategies`:
|
||||
.. _`cache file backends`:
|
||||
.. _`cache file strategies`:
|
||||
|
||||
|
||||
Conditional model ``processors``
|
||||
|
|
@ -100,12 +100,12 @@ solution: the custom ``spec``. See the `advanced usage`_ documentation for more.
|
|||
Conditonal ``cache_to`` file names
|
||||
----------------------------------
|
||||
|
||||
IK2 provided a means of specifying custom generated file names for your
|
||||
IK2 provided a means of specifying custom cache file names for your
|
||||
image specs by passing a ``cache_to`` callable to an ``ImageSpecField``.
|
||||
IK3 does away with this feature, again, for consistency.
|
||||
|
||||
There is a way to achieve custom file names by overriding your spec's
|
||||
``generatedfile_name``, but it is not recommended, as the spec's default
|
||||
``cachefile_name``, but it is not recommended, as the spec's default
|
||||
behavior is to hash the combination of ``source``, ``processors``, ``format``,
|
||||
and other spec options to ensure that changes to the spec always result in
|
||||
unique file names. See the documentation on `specs`_ for more.
|
||||
|
|
|
|||
|
|
@ -12,32 +12,32 @@ class GeneratedImageFile(BaseIKFile, ImageFile):
|
|||
A file that represents the result of a generator. Creating an instance of
|
||||
this class is not enough to trigger the generation of the file. In fact,
|
||||
one of the main points of this class is to allow the creation of the file
|
||||
to be deferred until the time that the generated file strategy requires it.
|
||||
to be deferred until the time that the cache file strategy requires it.
|
||||
|
||||
"""
|
||||
def __init__(self, generator, name=None, storage=None, generatedfile_backend=None):
|
||||
def __init__(self, generator, name=None, storage=None, cachefile_backend=None):
|
||||
"""
|
||||
:param generator: The object responsible for generating a new image.
|
||||
:param name: The filename
|
||||
:param storage: A Django storage object that will be used to save the
|
||||
file.
|
||||
:param generatedfile_backend: The object responsible for managing the
|
||||
:param cachefile_backend: The object responsible for managing the
|
||||
state of the file.
|
||||
|
||||
"""
|
||||
self.generator = generator
|
||||
|
||||
name = name or getattr(generator, 'generatedfile_name', None)
|
||||
name = name or getattr(generator, 'cachefile_name', None)
|
||||
if not name:
|
||||
fn = get_by_qname(settings.IMAGEKIT_GENERATEDFILE_NAMER, 'namer')
|
||||
fn = get_by_qname(settings.IMAGEKIT_CACHEFILE_NAMER, 'namer')
|
||||
name = fn(generator)
|
||||
self.name = name
|
||||
|
||||
storage = storage or getattr(generator, 'generatedfile_storage',
|
||||
storage = storage or getattr(generator, 'cachefile_storage',
|
||||
None) or get_singleton(settings.IMAGEKIT_DEFAULT_FILE_STORAGE,
|
||||
'file storage backend')
|
||||
self.generatedfile_backend = generatedfile_backend or getattr(generator,
|
||||
'generatedfile_backend', None)
|
||||
self.cachefile_backend = cachefile_backend or getattr(generator,
|
||||
'cachefile_backend', None)
|
||||
|
||||
super(GeneratedImageFile, self).__init__(storage=storage)
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ class GeneratedImageFile(BaseIKFile, ImageFile):
|
|||
if force:
|
||||
self._generate()
|
||||
else:
|
||||
self.generatedfile_backend.ensure_exists(self)
|
||||
self.cachefile_backend.ensure_exists(self)
|
||||
|
||||
def _generate(self):
|
||||
# Generate the file
|
||||
|
|
@ -66,7 +66,7 @@ class GeneratedImageFile(BaseIKFile, ImageFile):
|
|||
' race condition in the file backend %s. The saved file'
|
||||
' will not be used.' % (self.storage,
|
||||
self.name, actual_name,
|
||||
self.generatedfile_backend))
|
||||
self.cachefile_backend))
|
||||
|
||||
|
||||
class LazyGeneratedImageFile(LazyObject):
|
||||
|
|
@ -3,13 +3,13 @@ from django.core.cache import get_cache
|
|||
from django.core.exceptions import ImproperlyConfigured
|
||||
|
||||
|
||||
def get_default_generatedfile_backend():
|
||||
def get_default_cachefile_backend():
|
||||
"""
|
||||
Get the default file backend.
|
||||
|
||||
"""
|
||||
from django.conf import settings
|
||||
return get_singleton(settings.IMAGEKIT_DEFAULT_GENERATEDFILE_BACKEND,
|
||||
return get_singleton(settings.IMAGEKIT_DEFAULT_CACHEFILE_BACKEND,
|
||||
'file backend')
|
||||
|
||||
|
||||
|
|
@ -21,18 +21,18 @@ def source_name_as_path(generator):
|
|||
/path/to/generated/images/photos/thumbnails/bulldog/5ff3233527c5ac3e4b596343b440ff67.jpg
|
||||
|
||||
where "/path/to/generated/images/" is the value specified by the
|
||||
``IMAGEKIT_GENERATEDFILE_DIR`` setting.
|
||||
``IMAGEKIT_CACHEFILE_DIR`` setting.
|
||||
|
||||
"""
|
||||
source_filename = getattr(generator.source, 'name', None)
|
||||
|
||||
if source_filename is None or os.path.isabs(source_filename):
|
||||
# Generally, we put the file right in the generated file directory.
|
||||
dir = settings.IMAGEKIT_GENERATEDFILE_DIR
|
||||
# Generally, we put the file right in the cache file directory.
|
||||
dir = settings.IMAGEKIT_CACHEFILE_DIR
|
||||
else:
|
||||
# For source files with relative names (like Django media files),
|
||||
# use the source's name to create the new filename.
|
||||
dir = os.path.join(settings.IMAGEKIT_GENERATEDFILE_DIR,
|
||||
dir = os.path.join(settings.IMAGEKIT_CACHEFILE_DIR,
|
||||
os.path.splitext(source_filename)[0])
|
||||
|
||||
ext = suggest_extension(source_filename or '', generator.format)
|
||||
|
|
@ -51,18 +51,18 @@ def source_name_dot_hash(generator):
|
|||
/path/to/generated/images/photos/thumbnails/bulldog.5ff3233527c5.jpg
|
||||
|
||||
where "/path/to/generated/images/" is the value specified by the
|
||||
``IMAGEKIT_GENERATEDFILE_DIR`` setting.
|
||||
``IMAGEKIT_CACHEFILE_DIR`` setting.
|
||||
|
||||
"""
|
||||
source_filename = getattr(generator.source, 'name', None)
|
||||
|
||||
if source_filename is None or os.path.isabs(source_filename):
|
||||
# Generally, we put the file right in the generated file directory.
|
||||
dir = settings.IMAGEKIT_GENERATEDFILE_DIR
|
||||
# Generally, we put the file right in the cache file directory.
|
||||
dir = settings.IMAGEKIT_CACHEFILE_DIR
|
||||
else:
|
||||
# For source files with relative names (like Django media files),
|
||||
# use the source's name to create the new filename.
|
||||
dir = os.path.join(settings.IMAGEKIT_GENERATEDFILE_DIR,
|
||||
dir = os.path.join(settings.IMAGEKIT_CACHEFILE_DIR,
|
||||
os.path.dirname(source_filename))
|
||||
|
||||
ext = suggest_extension(source_filename or '', generator.format)
|
||||
|
|
@ -82,10 +82,10 @@ def hash(generator):
|
|||
/path/to/generated/images/5ff3233527c5ac3e4b596343b440ff67.jpg
|
||||
|
||||
where "/path/to/generated/images/" is the value specified by the
|
||||
``IMAGEKIT_GENERATEDFILE_DIR`` setting.
|
||||
``IMAGEKIT_CACHEFILE_DIR`` setting.
|
||||
|
||||
"""
|
||||
format = getattr(generator, 'format', None)
|
||||
ext = format_to_extension(format) if format else ''
|
||||
return os.path.normpath(os.path.join(settings.IMAGEKIT_GENERATEDFILE_DIR,
|
||||
return os.path.normpath(os.path.join(settings.IMAGEKIT_CACHEFILE_DIR,
|
||||
'%s%s' % (generator.get_hash(), ext)))
|
||||
|
|
@ -15,8 +15,8 @@ class JustInTime(object):
|
|||
class Optimistic(object):
|
||||
"""
|
||||
A strategy that acts immediately when the source file changes and assumes
|
||||
that the generated files will not be removed (i.e. it doesn't ensure the
|
||||
generated file exists when it's accessed).
|
||||
that the cache files will not be removed (i.e. it doesn't ensure the
|
||||
cache file exists when it's accessed).
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ class DictStrategy(object):
|
|||
class StrategyWrapper(LazyObject):
|
||||
def __init__(self, strategy):
|
||||
if isinstance(strategy, basestring):
|
||||
strategy = get_singleton(strategy, 'generated file strategy')
|
||||
strategy = get_singleton(strategy, 'cache file strategy')
|
||||
elif isinstance(strategy, dict):
|
||||
strategy = DictStrategy(strategy)
|
||||
elif callable(strategy):
|
||||
|
|
@ -3,11 +3,11 @@ from django.conf import settings
|
|||
|
||||
|
||||
class ImageKitConf(AppConf):
|
||||
GENERATEDFILE_NAMER = 'imagekit.generatedfiles.namers.hash'
|
||||
SPEC_GENERATEDFILE_NAMER = 'imagekit.generatedfiles.namers.source_name_as_path'
|
||||
GENERATEDFILE_DIR = 'generated/images'
|
||||
DEFAULT_GENERATEDFILE_BACKEND = 'imagekit.generatedfiles.backends.Simple'
|
||||
DEFAULT_GENERATEDFILE_STRATEGY = 'imagekit.generatedfiles.strategies.JustInTime'
|
||||
CACHEFILE_NAMER = 'imagekit.cachefiles.namers.hash'
|
||||
SPEC_CACHEFILE_NAMER = 'imagekit.cachefiles.namers.source_name_as_path'
|
||||
CACHEFILE_DIR = 'CACHE/images'
|
||||
DEFAULT_CACHEFILE_BACKEND = 'imagekit.cachefiles.backends.Simple'
|
||||
DEFAULT_CACHEFILE_STRATEGY = 'imagekit.cachefiles.strategies.JustInTime'
|
||||
|
||||
DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage'
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from django.core.management.base import BaseCommand
|
||||
import re
|
||||
from ...registry import generator_registry, generatedfile_registry
|
||||
from ...registry import generator_registry, cachefile_registry
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
|
|
@ -22,7 +22,7 @@ well as "a:b" and "a:b:c".""")
|
|||
|
||||
for generator_id in generators:
|
||||
self.stdout.write('Validating generator: %s\n' % generator_id)
|
||||
for file in generatedfile_registry.get(generator_id):
|
||||
for file in cachefile_registry.get(generator_id):
|
||||
self.stdout.write(' %s\n' % file)
|
||||
try:
|
||||
# TODO: Allow other validation actions through command option
|
||||
|
|
|
|||
|
|
@ -26,15 +26,15 @@ class ImageSpecField(SpecHostField):
|
|||
|
||||
"""
|
||||
def __init__(self, processors=None, format=None, options=None,
|
||||
source=None, generatedfile_storage=None, autoconvert=None,
|
||||
generatedfile_backend=None, generatedfile_strategy=None, spec=None,
|
||||
source=None, cachefile_storage=None, autoconvert=None,
|
||||
cachefile_backend=None, cachefile_strategy=None, spec=None,
|
||||
id=None):
|
||||
|
||||
SpecHost.__init__(self, processors=processors, format=format,
|
||||
options=options, generatedfile_storage=generatedfile_storage,
|
||||
options=options, cachefile_storage=cachefile_storage,
|
||||
autoconvert=autoconvert,
|
||||
generatedfile_backend=generatedfile_backend,
|
||||
generatedfile_strategy=generatedfile_strategy, spec=spec,
|
||||
cachefile_backend=cachefile_backend,
|
||||
cachefile_strategy=cachefile_strategy, spec=spec,
|
||||
spec_id=id)
|
||||
|
||||
# TODO: Allow callable for source. See https://github.com/jdriscoll/django-imagekit/issues/158#issuecomment-10921664
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from ...generatedfiles import GeneratedImageFile
|
||||
from ...cachefiles import GeneratedImageFile
|
||||
from django.db.models.fields.files import ImageField
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ class SourceGroupRegistry(object):
|
|||
from .specs.sourcegroups import SourceGroupFilesGenerator
|
||||
generator_ids = self._source_groups.setdefault(source_group, set())
|
||||
generator_ids.add(generator_id)
|
||||
generatedfile_registry.register(generator_id,
|
||||
cachefile_registry.register(generator_id,
|
||||
SourceGroupFilesGenerator(source_group, generator_id))
|
||||
|
||||
def unregister(self, generator_id, source_group):
|
||||
|
|
@ -84,7 +84,7 @@ class SourceGroupRegistry(object):
|
|||
generator_ids = self._source_groups.setdefault(source_group, set())
|
||||
if generator_id in generator_ids:
|
||||
generator_ids.remove(generator_id)
|
||||
generatedfile_registry.unregister(generator_id,
|
||||
cachefile_registry.unregister(generator_id,
|
||||
SourceGroupFilesGenerator(source_group, generator_id))
|
||||
|
||||
def source_group_receiver(self, sender, source, signal, **kwargs):
|
||||
|
|
@ -92,7 +92,7 @@ class SourceGroupRegistry(object):
|
|||
Relay source group signals to the appropriate spec strategy.
|
||||
|
||||
"""
|
||||
from .generatedfiles import GeneratedImageFile
|
||||
from .cachefiles import GeneratedImageFile
|
||||
source_group = sender
|
||||
|
||||
# Ignore signals from unregistered groups.
|
||||
|
|
@ -108,11 +108,11 @@ class SourceGroupRegistry(object):
|
|||
call_strategy_method(spec, callback_name, file=file)
|
||||
|
||||
|
||||
class GeneratedFileRegistry(object):
|
||||
class CacheFileRegistry(object):
|
||||
"""
|
||||
An object for registering generated files with image generators. The two are
|
||||
associated with each other via a string id. We do this (as opposed to
|
||||
associating them directly by, for example, putting a ``generatedfiles``
|
||||
associating them directly by, for example, putting a ``cachefiles``
|
||||
attribute on image generators) so that image generators can be overridden
|
||||
without losing the associated files. That way, a distributable app can
|
||||
define its own generators without locking the users of the app into it.
|
||||
|
|
@ -120,29 +120,29 @@ class GeneratedFileRegistry(object):
|
|||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._generatedfiles = {}
|
||||
self._cachefiles = {}
|
||||
|
||||
def register(self, generator_id, generatedfiles):
|
||||
def register(self, generator_id, cachefiles):
|
||||
"""
|
||||
Associates generated files with a generator id
|
||||
|
||||
"""
|
||||
if generatedfiles not in self._generatedfiles:
|
||||
self._generatedfiles[generatedfiles] = set()
|
||||
self._generatedfiles[generatedfiles].add(generator_id)
|
||||
if cachefiles not in self._cachefiles:
|
||||
self._cachefiles[cachefiles] = set()
|
||||
self._cachefiles[cachefiles].add(generator_id)
|
||||
|
||||
def unregister(self, generator_id, generatedfiles):
|
||||
def unregister(self, generator_id, cachefiles):
|
||||
"""
|
||||
Disassociates generated files with a generator id
|
||||
|
||||
"""
|
||||
try:
|
||||
self._generatedfiles[generatedfiles].remove(generator_id)
|
||||
self._cachefiles[cachefiles].remove(generator_id)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def get(self, generator_id):
|
||||
for k, v in self._generatedfiles.items():
|
||||
for k, v in self._cachefiles.items():
|
||||
if generator_id in v:
|
||||
for file in k():
|
||||
yield file
|
||||
|
|
@ -164,8 +164,8 @@ class Register(object):
|
|||
generator_registry.register(id, generator)
|
||||
|
||||
# iterable that returns kwargs or callable that returns iterable of kwargs
|
||||
def generatedfiles(self, generator_id, generatedfiles):
|
||||
generatedfile_registry.register(generator_id, generatedfiles)
|
||||
def cachefiles(self, generator_id, cachefiles):
|
||||
cachefile_registry.register(generator_id, cachefiles)
|
||||
|
||||
def source_group(self, generator_id, source_group):
|
||||
source_group_registry.register(generator_id, source_group)
|
||||
|
|
@ -179,15 +179,15 @@ class Unregister(object):
|
|||
def generator(self, id, generator):
|
||||
generator_registry.unregister(id, generator)
|
||||
|
||||
def generatedfiles(self, generator_id, generatedfiles):
|
||||
generatedfile_registry.unregister(generator_id, generatedfiles)
|
||||
def cachefiles(self, generator_id, cachefiles):
|
||||
cachefile_registry.unregister(generator_id, cachefiles)
|
||||
|
||||
def source_group(self, generator_id, source_group):
|
||||
source_group_registry.unregister(generator_id, source_group)
|
||||
|
||||
|
||||
generator_registry = GeneratorRegistry()
|
||||
generatedfile_registry = GeneratedFileRegistry()
|
||||
cachefile_registry = CacheFileRegistry()
|
||||
source_group_registry = SourceGroupRegistry()
|
||||
register = Register()
|
||||
unregister = Unregister()
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ from django.conf import settings
|
|||
from django.db.models.fields.files import ImageFieldFile
|
||||
from hashlib import md5
|
||||
import pickle
|
||||
from ..generatedfiles.backends import get_default_generatedfile_backend
|
||||
from ..generatedfiles.strategies import StrategyWrapper
|
||||
from ..cachefiles.backends import get_default_cachefile_backend
|
||||
from ..cachefiles.strategies import StrategyWrapper
|
||||
from ..processors import ProcessorPipeline
|
||||
from ..utils import open_image, img_to_fobj, get_by_qname
|
||||
from ..registry import generator_registry, register
|
||||
|
|
@ -16,27 +16,27 @@ class BaseImageSpec(object):
|
|||
|
||||
"""
|
||||
|
||||
generatedfile_storage = None
|
||||
"""A Django storage system to use to save a generated file."""
|
||||
cachefile_storage = None
|
||||
"""A Django storage system to use to save a cache file."""
|
||||
|
||||
generatedfile_backend = None
|
||||
cachefile_backend = None
|
||||
"""
|
||||
An object responsible for managing the state of generated files. Defaults to
|
||||
an instance of ``IMAGEKIT_DEFAULT_GENERATEDFILE_BACKEND``
|
||||
An object responsible for managing the state of cache files. Defaults to
|
||||
an instance of ``IMAGEKIT_DEFAULT_CACHEFILE_BACKEND``
|
||||
|
||||
"""
|
||||
|
||||
generatedfile_strategy = settings.IMAGEKIT_DEFAULT_GENERATEDFILE_STRATEGY
|
||||
cachefile_strategy = settings.IMAGEKIT_DEFAULT_CACHEFILE_STRATEGY
|
||||
"""
|
||||
A dictionary containing callbacks that allow you to customize how and when
|
||||
the image file is created. Defaults to
|
||||
``IMAGEKIT_DEFAULT_GENERATEDFILE_STRATEGY``.
|
||||
``IMAGEKIT_DEFAULT_CACHEFILE_STRATEGY``.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.generatedfile_backend = self.generatedfile_backend or get_default_generatedfile_backend()
|
||||
self.generatedfile_strategy = StrategyWrapper(self.generatedfile_strategy)
|
||||
self.cachefile_backend = self.cachefile_backend or get_default_cachefile_backend()
|
||||
self.cachefile_strategy = StrategyWrapper(self.cachefile_strategy)
|
||||
|
||||
def generate(self):
|
||||
raise NotImplementedError
|
||||
|
|
@ -81,8 +81,8 @@ class ImageSpec(BaseImageSpec):
|
|||
super(ImageSpec, self).__init__()
|
||||
|
||||
@property
|
||||
def generatedfile_name(self):
|
||||
fn = get_by_qname(settings.IMAGEKIT_SPEC_GENERATEDFILE_NAMER, 'namer')
|
||||
def cachefile_name(self):
|
||||
fn = get_by_qname(settings.IMAGEKIT_SPEC_CACHEFILE_NAMER, 'namer')
|
||||
return fn(self)
|
||||
|
||||
def __getstate__(self):
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ Source groups are the means by which image spec sources are identified. They
|
|||
have two responsibilities:
|
||||
|
||||
1. To dispatch ``source_created``, ``source_changed``, and ``source_deleted``
|
||||
signals. (These will be relayed to the corresponding specs' generated file
|
||||
signals. (These will be relayed to the corresponding specs' cache file
|
||||
strategies.)
|
||||
2. To provide the source files that they represent, via a generator method named
|
||||
``files()``. (This is used by the generateimages management command for
|
||||
|
|
@ -13,7 +13,7 @@ have two responsibilities:
|
|||
|
||||
from django.db.models.signals import post_init, post_save, post_delete
|
||||
from django.utils.functional import wraps
|
||||
from ..generatedfiles import LazyGeneratedImageFile
|
||||
from ..cachefiles import LazyGeneratedImageFile
|
||||
from ..signals import source_created, source_changed, source_deleted
|
||||
|
||||
|
||||
|
|
@ -137,7 +137,7 @@ class ImageFieldSourceGroup(object):
|
|||
|
||||
class SourceGroupFilesGenerator(object):
|
||||
"""
|
||||
A Python generator that yields generated file objects for source groups.
|
||||
A Python generator that yields cache file objects for source groups.
|
||||
|
||||
"""
|
||||
def __init__(self, source_group, generator_id):
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ from django import template
|
|||
from django.utils.html import escape
|
||||
from django.utils.safestring import mark_safe
|
||||
from .compat import parse_bits
|
||||
from ..generatedfiles import GeneratedImageFile
|
||||
from ..cachefiles import GeneratedImageFile
|
||||
from ..registry import generator_registry
|
||||
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ HTML_ATTRS_DELIMITER = '--'
|
|||
DEFAULT_THUMBNAIL_GENERATOR = 'imagekit:thumbnail'
|
||||
|
||||
|
||||
def get_generatedfile(context, generator_id, generator_kwargs, source=None):
|
||||
def get_cachefile(context, generator_id, generator_kwargs, source=None):
|
||||
generator_id = generator_id.resolve(context)
|
||||
kwargs = dict((k, v.resolve(context)) for k, v in generator_kwargs.items())
|
||||
generator = generator_registry.get(generator_id, **kwargs)
|
||||
|
|
@ -47,7 +47,7 @@ class GenerateImageAssignmentNode(template.Node):
|
|||
autodiscover()
|
||||
|
||||
variable_name = self.get_variable_name(context)
|
||||
context[variable_name] = get_generatedfile(context, self._generator_id,
|
||||
context[variable_name] = get_cachefile(context, self._generator_id,
|
||||
self._generator_kwargs)
|
||||
return ''
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ class GenerateImageTagNode(template.Node):
|
|||
from ..utils import autodiscover
|
||||
autodiscover()
|
||||
|
||||
file = get_generatedfile(context, self._generator_id,
|
||||
file = get_cachefile(context, self._generator_id,
|
||||
self._generator_kwargs)
|
||||
attrs = dict((k, v.resolve(context)) for k, v in
|
||||
self._html_attrs.items())
|
||||
|
|
|
|||
|
|
@ -425,7 +425,7 @@ def generate(generator):
|
|||
|
||||
|
||||
def call_strategy_method(generator, method_name, *args, **kwargs):
|
||||
strategy = getattr(generator, 'generatedfile_strategy', None)
|
||||
strategy = getattr(generator, 'cachefile_strategy', None)
|
||||
fn = getattr(strategy, method_name, None)
|
||||
if fn is not None:
|
||||
fn(*args, **kwargs)
|
||||
|
|
|
|||
Loading…
Reference in a new issue