Starting advanced usage docs

This commit is contained in:
Matthew Tretter 2013-02-02 21:48:41 -05:00
parent 36c0757417
commit 1a7c0627df
2 changed files with 147 additions and 0 deletions

View file

@ -0,0 +1,99 @@
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.

View file

@ -0,0 +1,48 @@
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*.
Cache!
------
By default, ImageKit checks for the existence of a generated 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
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
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 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 "just in time" strategy determines whether a file needs to be generated each
time it's accessed and, if it does, generates it synchronously.
__ https://docs.djangoproject.com/en/dev/ref/files/storage/