mirror of
https://github.com/Hopiu/django-imagekit.git
synced 2026-03-16 21:30:23 +00:00
Starting advanced usage docs
This commit is contained in:
parent
36c0757417
commit
1a7c0627df
2 changed files with 147 additions and 0 deletions
99
docs/advanced_usage/models.rst
Normal file
99
docs/advanced_usage/models.rst
Normal 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.
|
||||
48
docs/advanced_usage/optimizing.rst
Normal file
48
docs/advanced_usage/optimizing.rst
Normal 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/
|
||||
Loading…
Reference in a new issue