From 1f86e33d64bee2b975344223058520c0f84f77dc Mon Sep 17 00:00:00 2001 From: Matthew Tretter Date: Tue, 5 Feb 2013 21:12:39 -0500 Subject: [PATCH] Doc fixes --- AUTHORS | 4 +- README.rst | 6 +- docs/advanced_usage.rst | 284 ++++++++++++++++++++++++++ docs/advanced_usage/models.rst | 99 --------- docs/advanced_usage/optimizing.rst | 101 --------- docs/advanced_usage/source_groups.rst | 69 ------- docs/apireference.rst | 29 --- docs/configuration.rst | 91 ++------- docs/index.rst | 40 +--- docs/upgrading.rst | 1 + 10 files changed, 314 insertions(+), 410 deletions(-) create mode 100644 docs/advanced_usage.rst delete mode 100644 docs/advanced_usage/models.rst delete mode 100644 docs/advanced_usage/optimizing.rst delete mode 100644 docs/advanced_usage/source_groups.rst delete mode 100644 docs/apireference.rst diff --git a/AUTHORS b/AUTHORS index 03028f2..d91cb93 100644 --- a/AUTHORS +++ b/AUTHORS @@ -4,7 +4,7 @@ The field-based API and other post-1.0 stuff was written by the bright people at HZDG_. Maintainers -~~~~~~~~~~~ +----------- * `Bryan Veloso`_ * `Matthew Tretter`_ @@ -12,7 +12,7 @@ Maintainers * `Greg Newman`_ Contributors -~~~~~~~~~~~~ +------------ * `Josh Ourisman`_ * `Jonathan Slenders`_ diff --git a/README.rst b/README.rst index 2846bab..2f2ad5d 100644 --- a/README.rst +++ b/README.rst @@ -94,7 +94,7 @@ class: This is pretty similar to our previous example. We don't need to specify a "source" any more since we're not processing another image field, but we do need to pass an "upload_to" argument. This behaves exactly as it does for Django -``ImageField``s. +ImageFields. .. note:: @@ -393,7 +393,7 @@ AdminThumbnail can even use a custom template. For more information, see Community ---------- +========= Please use `the GitHub issue tracker `_ to report bugs with django-imagekit. `A mailing list `_ @@ -402,7 +402,7 @@ also exists to discuss the project and ask questions, as well as the official Contributing ------------- +============ We love contributions! And you don't have to be an expert with the library—or even Django—to contribute either: ImageKit's processors are standalone classes diff --git a/docs/advanced_usage.rst b/docs/advanced_usage.rst new file mode 100644 index 0000000..917b642 --- /dev/null +++ b/docs/advanced_usage.rst @@ -0,0 +1,284 @@ +Advanced Usage +************** + + +Models +====== + + +The ``ImageSpecField`` Shorthand Syntax +--------------------------------------- + +If you've read the README, you already know what an ``ImageSpecField`` is and +the basics of defining one: + +.. code-block:: python + + from django.db import models + from imagekit.models import ImageSpecField + from imagekit.processors import ResizeToFill + + class Profile(models.Model): + avatar = models.ImageField(upload_to='avatars') + avatar_thumbnail = ImageSpecField(source='avatar', + processors=[ResizeToFill(100, 50)], + format='JPEG', + options={'quality': 60}) + +This will create an ``avatar_thumbnail`` field which is a resized version of the +image stored in the ``avatar`` image field. But this is actually just shorthand +for creating an ``ImageSpec``, registering it, and associating it with an +``ImageSpecField``: + +.. code-block:: python + + from django.db import models + from imagekit import ImageSpec, register + from imagekit.models import ImageSpecField + from imagekit.processors import ResizeToFill + + class AvatarThumbnail(ImageSpec): + processors = [ResizeToFill(100, 50)] + format = 'JPEG' + options = {'quality': 60} + + register.generator('myapp:profile:avatar_thumbnail', AvatarThumbnail) + + class Profile(models.Model): + avatar = models.ImageField(upload_to='avatars') + avatar_thumbnail = ImageSpecField(source='avatar', + spec_id='myapp:profile:avatar_thumbnail') + +Obviously, the shorthand version is a lot, well…shorter. So why would you ever +want to go through the trouble of using the long form? The answer is that the +long form—creating an image spec class and registering it—gives you a lot more +power over the generated image. + + +.. _dynamic-specs: + +Specs That Change +----------------- + +As you'll remember from the README, an image spec is just a type of image +generator that generates a new image from a source image. How does the image +spec get access to the source image? Simple! It's passed to the constructor as +a keyword argument and stored as an attribute of the spec. Normally, we don't +have to concern ourselves with this; the ``ImageSpec`` knows what to do with the +source image and we're happy to let it do its thing. However, having access to +the source image in our spec class can be very useful… + +Often, when using an ``ImageSpecField``, you may want the spec to vary based on +properties of a model. (For example, you might want to store image dimensions on +the model and then use them to generate your thumbnail.) Now that we know how to +access the source image from our spec, it's a simple matter to extract its model +and use it to create our processors list. In fact, ImageKit includes a utility +for getting this information. + +.. code-block:: python + :emphasize-lines: 11-14 + + from django.db import models + from imagekit import ImageSpec, register + from imagekit.models import ImageSpecField + from imagekit.processors import ResizeToFill + from imagekit.utils import get_field_info + + class AvatarThumbnail(ImageSpec): + format = 'JPEG' + options = {'quality': 60} + + @property + def processors(self): + model, field_name = get_field_info(self.source) + return [ResizeToFill(model.thumbnail_width, thumbnail.avatar_height)] + + register.generator('myapp:profile:avatar_thumbnail', AvatarThumbnail) + + class Profile(models.Model): + avatar = models.ImageField(upload_to='avatars') + avatar_thumbnail = ImageSpecField(source='avatar', + spec_id='myapp:profile:avatar_thumbnail') + thumbnail_width = models.PositiveIntegerField() + thumbnail_height = models.PositiveIntegerField() + +Now each avatar thumbnail will be resized according to the dimensions stored on +the model! + +Of course, processors aren't the only thing that can vary based on the model of +the source image; spec behavior can change in any way you want. + + +Optimizing +========== + +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 *cache file backend*. + + +Cache! +------ + +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 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 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. + + +Even More Advanced +------------------ + +For many applications—particularly those using local storage for generated image +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 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). + +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.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. + +With image specs, we can know at least some of the times that a new file needs +to be generated: whenever the source image is created or changed. For this +reason, the optimistic strategy defines callbacks for these events. Every +source registered with ImageKit will automatically cause its specs' files to be +generated when it is created or changed. + +.. note:: + + In order to understand source registration, read :ref:`source-groups` + +If you have specs that :ref:`change based on attributes of the source +`, that's not going to cut it, though; the file will also need to +be generated when those attributes change. Likewise, image generators that don't +have sources (i.e. generators that aren't specs) won't cause files to be +generated automatically when using the optimistic strategy. (ImageKit can't know +when those need to be generated, if not on access.) In both cases, you'll have +to trigger the file generation yourself—either by generating the file in code +when necessary, or by periodically running the ``generateimages`` management +command. Luckily, ImageKit makes this pretty easy: + +.. code-block:: python + + from imagekit.cachefiles import LazyGeneratedImageFile + + file = LazyGeneratedImageFile('myapp:profile:avatar_thumbnail', source=source_file) + file.generate() + +One final situation in which images won't be generated automatically when using +the optimistic strategy is when you use a spec with a source that hasn't been +registered with it. Unlike the previous two examples, this situation cannot be +rectified by running the ``generateimages`` management command, for the simple +reason that the command has no way of knowing it needs to generate a file for +that spec from that source. Typically, this situation would arise when using the +template tags. Unlike ImageSpecFields, which automatically register all the +possible source images with the spec you define, the template tags +("generateimage" and "thumbnail") let you use any spec with any source. +Therefore, in order to generate the appropriate files using the +``generateimages`` management command, you'll need to first register a source +group that represents all of the sources you wish to use with the corresponding +specs. See :ref:`source-groups` for more information. + + +.. _source-groups: + +Source Groups +============= + +When you run the ``generateimages`` management command, how does ImageKit know +which source images to use with which specs? Obviously, when you define an +ImageSpecField, the source image is being connected to a spec, but what's going +on underneath the hood? + +The answer is that, when you define an ImageSpecField, ImageKit automatically +creates and registers an object called a *source group*. Source groups are +responsible for two things: + +1. They dispatch signals when a source is created, changed, or deleted, and +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 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 +``generateimages`` management command. + +Currently, there is only one source group class bundled with ImageKit—the one +used by ImageSpecFields. This source group +(``imagekit.specs.sourcegroups.ImageFieldSourceGroup``) represents an ImageField +on every instance of a particular model. In terms of the above description, the +instance ``ImageFieldSourceGroup(Profile, 'avatar')`` 1) dispatches a signal +every time the image in Profile's avatar ImageField changes, and 2) exposes a +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 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 +opportunity to act on it). + +A simple example of a custom source group class is as follows: + +.. code-block:: python + + import glob + import os + + class JpegsInADirectory(object): + def __init__(self, dir): + self.dir = dir + + def files(self): + os.chdir(self.dir) + for name in glob.glob('*.jpg'): + yield open(name) + +Instances of this class could then be registered with one or more spec id: + +.. code-block:: python + + from imagekit import register + + register.source_group('myapp:profile:avatar_thumbnail', JpegsInADirectory('/path/to/some/pics')) + +Running the "generateimages" management command would now cause thumbnails to be +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 cache file strategy callbacks +would not be called for them. diff --git a/docs/advanced_usage/models.rst b/docs/advanced_usage/models.rst deleted file mode 100644 index 2ccd70d..0000000 --- a/docs/advanced_usage/models.rst +++ /dev/null @@ -1,99 +0,0 @@ -The ``ImageSpecField`` Shorthand Syntax ---------------------------------------- - -If you've read the README, you already know what an ``ImageSpecField`` is and -the basics of defining one: - -.. code-block:: python - - from django.db import models - from imagekit.models import ImageSpecField - from imagekit.processors import ResizeToFill - - class Profile(models.Model): - avatar = models.ImageField(upload_to='avatars') - avatar_thumbnail = ImageSpecField(source='avatar', - processors=[ResizeToFill(100, 50)], - format='JPEG', - options={'quality': 60}) - -This will create an ``avatar_thumbnail`` field which is a resized version of the -image stored in the ``avatar`` image field. But this is actually just shorthand -for creating an ``ImageSpec``, registering it, and associating it with an -``ImageSpecField``: - -.. code-block:: python - - from django.db import models - from imagekit import ImageSpec, register - from imagekit.models import ImageSpecField - from imagekit.processors import ResizeToFill - - class AvatarThumbnail(ImageSpec): - processors = [ResizeToFill(100, 50)] - format = 'JPEG' - options = {'quality': 60} - - register.generator('myapp:profile:avatar_thumbnail', AvatarThumbnail) - - class Profile(models.Model): - avatar = models.ImageField(upload_to='avatars') - avatar_thumbnail = ImageSpecField(source='avatar', - spec_id='myapp:profile:avatar_thumbnail') - -Obviously, the shorthand version is a lot, well…shorter. So why would you ever -want to go through the trouble of using the long form? The answer is that the -long form—creating an image spec class and registering it—gives you a lot more -power over the generated image. - - -Specs That Change ------------------ - -As you'll remember from the README, an image spec is just a type of image -generator that generates a new image from a source image. How does the image -spec get access to the source image? Simple! It's passed to the constructor as -a keyword argument and stored as an attribute of the spec. Normally, we don't -have to concern ourselves with this; the ``ImageSpec`` knows what to do with the -source image and we're happy to let it do its thing. However, having access to -the source image in our spec class can be very useful… - -Often, when using an ``ImageSpecField``, you may want the spec to vary based on -properties of a model. (For example, you might want to store image dimensions on -the model and then use them to generate your thumbnail.) Now that we know how to -access the source image from our spec, it's a simple matter to extract its model -and use it to create our processors list. In fact, ImageKit includes a utility -for getting this information. - -.. code-block:: python - :emphasize-lines: 11-14 - - from django.db import models - from imagekit import ImageSpec, register - from imagekit.models import ImageSpecField - from imagekit.processors import ResizeToFill - from imagekit.utils import get_field_info - - class AvatarThumbnail(ImageSpec): - format = 'JPEG' - options = {'quality': 60} - - @property - def processors(self): - model, field_name = get_field_info(self.source) - return [ResizeToFill(model.thumbnail_width, thumbnail.avatar_height)] - - register.generator('myapp:profile:avatar_thumbnail', AvatarThumbnail) - - class Profile(models.Model): - avatar = models.ImageField(upload_to='avatars') - avatar_thumbnail = ImageSpecField(source='avatar', - spec_id='myapp:profile:avatar_thumbnail') - thumbnail_width = models.PositiveIntegerField() - thumbnail_height = models.PositiveIntegerField() - -Now each avatar thumbnail will be resized according to the dimensions stored on -the model! - -Of course, processors aren't the only thing that can vary based on the model of -the source image; spec behavior can change in any way you want. diff --git a/docs/advanced_usage/optimizing.rst b/docs/advanced_usage/optimizing.rst deleted file mode 100644 index b28c583..0000000 --- a/docs/advanced_usage/optimizing.rst +++ /dev/null @@ -1,101 +0,0 @@ -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 *cache file backend*. - - -Cache! ------- - -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 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 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. - - -Even More Advanced ------------------- - -For many applications—particularly those using local storage for generated image -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 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). - -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.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. - -With image specs, we can know at least some of the times that a new file needs -to be generated: whenever the source image is created or changed. For this -reason, the optimistic strategy defines callbacks for these events. Every -`source registered with ImageKit`__ will automatically cause its specs' files to -be generated when it is created or changed. - -.. note:: - - In order to understand source registration, read :ref:`source-groups` - -If you have specs that `change based on attributes of the source`__, that's not -going to cut it, though; the file will also need to be generated when those -attributes change. Likewise, image generators that don't have sources (i.e. -generators that aren't specs) won't cause files to be generated automatically -when using the optimistic strategy. (ImageKit can't know when those need to be -generated, if not on access.) In both cases, you'll have to trigger the file -generation yourself—either by generating the file in code when necessary, or by -periodically running the ``generateimages`` management command. Luckily, -ImageKit makes this pretty easy: - -.. code-block:: python - - from imagekit.cachefiles import LazyGeneratedImageFile - - file = LazyGeneratedImageFile('myapp:profile:avatar_thumbnail', source=source_file) - file.generate() - -One final situation in which images won't be generated automatically when using -the optimistic strategy is when you use a spec with a source that hasn't been -registered with it. Unlike the previous two examples, this situation cannot be -rectified by running the ``generateimages`` management command, for the simple -reason that the command has no way of knowing it needs to generate a file for -that spec from that source. Typically, this situation would arise when using the -template tags. Unlike ImageSpecFields, which automatically register all the -possible source images with the spec you define, the template tags -("generateimage" and "thumbnail") let you use any spec with any source. -Therefore, in order to generate the appropriate files using the -``generateimages`` management command, you'll need to first register a source -group that represents all of the sources you wish to use with the corresponding -specs. See :ref:`source-groups` for more information. - - -__ https://docs.djangoproject.com/en/dev/ref/files/storage/ -__ -__ diff --git a/docs/advanced_usage/source_groups.rst b/docs/advanced_usage/source_groups.rst deleted file mode 100644 index d3ba0e5..0000000 --- a/docs/advanced_usage/source_groups.rst +++ /dev/null @@ -1,69 +0,0 @@ -.. _source-groups: - -When you run the ``generateimages`` management command, how does ImageKit know -which source images to use with which specs? Obviously, when you define an -ImageSpecField, the source image is being connected to a spec, but what's going -on underneath the hood? - -The answer is that, when you define an ImageSpecField, ImageKit automatically -creates and registers an object called a *source group*. Source groups are -responsible for two things: - -1. They dispatch signals when a source is created, changed, or deleted, and -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 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 -``generateimages`` management command. - -Currently, there is only one source group class bundled with ImageKit—the one -used by ImageSpecFields. This source group -(``imagekit.specs.sourcegroups.ImageFieldSourceGroup``) represents an ImageField -on every instance of a particular model. In terms of the above description, the -instance ``ImageFieldSourceGroup(Profile, 'avatar')`` 1) dispatches a signal -every time the image in Profile's avatar ImageField changes, and 2) exposes a -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 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 -opportunity to act on it). - -A simple example of a custom source group class is as follows: - -.. code-block:: python - - import glob - import os - - class JpegsInADirectory(object): - def __init__(self, dir): - self.dir = dir - - def files(self): - os.chdir(self.dir) - for name in glob.glob('*.jpg'): - yield open(name) - -Instances of this class could then be registered with one or more spec id: - -.. code-block:: python - - from imagekit import register - - register.source_group('myapp:profile:avatar_thumbnail', JpegsInADirectory('/path/to/some/pics')) - -Running the "generateimages" management command would now cause thumbnails to be -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 cache file strategy callbacks -would not be called for them. diff --git a/docs/apireference.rst b/docs/apireference.rst deleted file mode 100644 index d4a2ed8..0000000 --- a/docs/apireference.rst +++ /dev/null @@ -1,29 +0,0 @@ -API Reference -============= - - -:mod:`models` Module --------------------- - -.. automodule:: imagekit.models.fields - :members: - - -:mod:`processors` Module ------------------------- - -.. automodule:: imagekit.processors - :members: - -.. automodule:: imagekit.processors.resize - :members: - -.. automodule:: imagekit.processors.crop - :members: - - -:mod:`admin` Module --------------------- - -.. automodule:: imagekit.admin - :members: diff --git a/docs/configuration.rst b/docs/configuration.rst index 18b3595..6216158 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -10,7 +10,7 @@ Settings .. currentmodule:: django.conf.settings -.. attribute:: IMAGEKIT_CACHE_DIR +.. attribute:: IMAGEKIT_CACHEFILE_DIR :default: ``'CACHE/images'`` @@ -27,16 +27,16 @@ Settings will be used. -.. attribute:: IMAGEKIT_DEFAULT_IMAGE_CACHE_BACKEND +.. attribute:: IMAGEKIT_DEFAULT_CACHEFILE_BACKEND - :default: ``'imagekit.imagecache.backends.Simple'`` + :default: ``'imagekit.cachefiles.backends.Simple'`` Specifies the class that will be used to validate cached image files. -.. attribute:: IMAGEKIT_DEFAULT_IMAGE_CACHE_STRATEGY +.. attribute:: IMAGEKIT_DEFAULT_CACHEFILE_STRATEGY - :default: ``'imagekit.imagecache.strategies.JustInTime'`` + :default: ``'imagekit.cachefiles.strategies.JustInTime'`` The class responsible for specifying how and when cache files are generated. @@ -58,80 +58,17 @@ Settings A cache prefix to be used when values are stored in ``IMAGEKIT_CACHE_BACKEND`` -Optimization ------------- +.. attribute:: IMAGEKIT_CACHEFILE_NAMER -Not surprisingly, the trick to getting the most out of ImageKit is to reduce the -number of I/O operations. This can be especially important if your source files -aren't stored on the same server as the application. + :default: ``'imagekit.cachefiles.namers.hash'`` + + A function responsible for generating file names for non-spec cache files. -Image Cache Strategies -^^^^^^^^^^^^^^^^^^^^^^ +.. attribute:: IMAGEKIT_SPEC_CACHEFILE_NAMER -An important way of reducing the number of I/O operations that ImageKit makes is -by controlling when cached images are validated. This is done through "image -cache strategies"—objects that associate signals dispatched on the source file -with file actions. The default image cache strategy is -``'imagekit.imagecache.strategies.JustInTime'``; it looks like this: + :default: ``'imagekit.cachefiles.namers.source_name_as_path'`` -.. code-block:: python - - class JustInTime(object): - def before_access(self, file): - validate_now(file) - -When this strategy is used, the cache file is validated only immediately before -it's required—for example, when you access its url, path, or contents. This -strategy is exceedingly safe: by guaranteeing the presence of the file before -accessing it, you run no risk of it not being there. However, this strategy can -also be costly: verifying the existence of the cache file every time you access -it can be slow—particularly if the file is on another server. For this reason, -ImageKit provides another strategy: ``imagekit.imagecache.strategies.Optimistic``. -Unlike the just-in-time strategy, it does not validate the cache file when it's -accessed, but rather only when the soure file is created or changed. Later, when -the cache file is accessed, it is presumed to still be present. - -If neither of these strategies suits your application, you can create your own -strategy class. For example, you may wish to validate the file immediately when -it's accessed, but schedule validation using Celery when the source file is -saved or changed: - -.. code-block:: python - - from imagekit.imagecache.actions import validate_now, deferred_validate - - class CustomImageCacheStrategy(object): - - def before_access(self, file): - validate_now(file) - - def on_source_created(self, file): - deferred_validate(file) - - def on_source_changed(self, file): - deferred_validate(file) - -To use this cache strategy, you need only set the ``IMAGEKIT_DEFAULT_IMAGE_CACHE_STRATEGY`` -setting, or set the ``image_cache_strategy`` attribute of your image spec. - - -Django Cache Backends -^^^^^^^^^^^^^^^^^^^^^ - -In the "Image Cache Strategies" section above, we said that the just-in-time -strategy verifies the existence of the cache file every time you access -it, however, that's not exactly true. Cache files are actually validated using -image cache backends, and the default (``imagekit.imagecache.backends.Simple``) -memoizes the cache state (valid or invalid) using Django's cache framework. By -default, ImageKit will use a dummy cache backend when your project is in debug -mode (``DEBUG = True``), and the "default" cache (from your ``CACHES`` setting) -when ``DEBUG`` is ``False``. Since other parts of your project may have -different cacheing needs, though, ImageKit has an ``IMAGEKIT_CACHE_BACKEND`` -setting, which allows you to specify a different cache. - -In most cases, you won't be deleting you cached files once they're created, so -using a cache with a large timeout is a great way to optimize your site. Using -a cache that never expires would essentially negate the cost of the just-in-time -strategy, giving you the benefit of generating images on demand without the cost -of unnecessary future filesystem checks. + A function responsible for generating file names for cache files that + correspond to image specs. Since you will likely want to base the name of + your cache files on the name of the source, this extra setting is provided. diff --git a/docs/index.rst b/docs/index.rst index 5484351..04eee0f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,44 +1,24 @@ -Getting Started -=============== - .. include:: ../README.rst -Commands --------- - -.. automodule:: imagekit.management.commands.ikcacheinvalidate - -.. automodule:: imagekit.management.commands.ikcachevalidate - - Authors -------- +======= .. include:: ../AUTHORS -Community ---------- - -The official Freenode channel for ImageKit is `#imagekit `_. -You should always find some fine people to answer your questions -about ImageKit there. - - -Digging Deeper --------------- - -.. toctree:: - - configuration - apireference - changelog - - Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` + +.. toctree:: + :glob: + :maxdepth: 2 + + configuration + advanced_usage + changelog + upgrading diff --git a/docs/upgrading.rst b/docs/upgrading.rst index 7a9b438..4efe7c0 100644 --- a/docs/upgrading.rst +++ b/docs/upgrading.rst @@ -5,6 +5,7 @@ ImageKit 3.0 introduces new APIs and tools that augment, improve, and in some cases entirely replace old IK workflows. Below, you'll find some useful guides for migrating your ImageKit 2.0 apps over to the shiny new IK3. + Model Specs -----------