mirror of
https://github.com/Hopiu/django-imagekit.git
synced 2026-04-08 23:40:59 +00:00
Update docs
This will be great when 3.0 is ready, but it'll also serve as a nice guide for us as we develop.
This commit is contained in:
parent
93409c8f05
commit
5fe5a73cb1
1 changed files with 189 additions and 98 deletions
287
README.rst
287
README.rst
|
|
@ -1,6 +1,7 @@
|
|||
ImageKit is a Django app that helps you to add variations of uploaded images
|
||||
to your models. These variations are called "specs" and can include things
|
||||
like different sizes (e.g. thumbnails) and black and white versions.
|
||||
ImageKit is a Django app for processing images. Need a thumbnail? A
|
||||
black-and-white version of a user-uploaded image? ImageKit will make them for
|
||||
you. If you need to programatically generate one image from another, you need
|
||||
ImageKit.
|
||||
|
||||
**For the complete documentation on the latest stable version of ImageKit, see**
|
||||
`ImageKit on RTD`_. Our `changelog is also available`_.
|
||||
|
|
@ -10,10 +11,10 @@ like different sizes (e.g. thumbnails) and black and white versions.
|
|||
|
||||
|
||||
Installation
|
||||
------------
|
||||
============
|
||||
|
||||
1. Install `PIL`_ or `Pillow`_. If you're using an ``ImageField`` in Django,
|
||||
you should have already done this.
|
||||
1. Install `PIL`_ or `Pillow`_. (If you're using an ``ImageField`` in Django,
|
||||
you should have already done this.)
|
||||
2. ``pip install django-imagekit``
|
||||
(or clone the source and put the imagekit module on your path)
|
||||
3. Add ``'imagekit'`` to your ``INSTALLED_APPS`` list in your project's settings.py
|
||||
|
|
@ -27,11 +28,90 @@ Installation
|
|||
.. _`Pillow`: http://pypi.python.org/pypi/Pillow
|
||||
|
||||
|
||||
Adding Specs to a Model
|
||||
-----------------------
|
||||
Usage Overview
|
||||
==============
|
||||
|
||||
Much like ``django.db.models.ImageField``, Specs are defined as properties
|
||||
of a model class:
|
||||
|
||||
Specs
|
||||
-----
|
||||
|
||||
You have one image and you want to do something to it to create another image.
|
||||
That's the basic use case of ImageKit. But how do you tell ImageKit what to do?
|
||||
By defining an "image spec." Specs are instructions for creating a new image
|
||||
from an existing one, and there are a few ways to define one. The most basic
|
||||
way is by defining an ``ImageSpec`` subclass:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from imagekit import ImageSpec
|
||||
from imagekit.processors import ResizeToFill
|
||||
|
||||
class Thumbnail(ImageSpec):
|
||||
processors = [ResizeToFill(100, 50)]
|
||||
format = 'JPEG'
|
||||
options = {'quality': 60}
|
||||
|
||||
Now that you've defined a spec, it's time to use it. The nice thing about specs
|
||||
is that they can be used in many different contexts.
|
||||
|
||||
Sometimes, you may want to just use a spec to generate a new image file. This
|
||||
might be useful, for example, in view code, or in scripts:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
????????
|
||||
|
||||
More often, however, you'll want to register your spec with ImageKit:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from imagekit import specs
|
||||
specs.register('myapp:fancy_thumbnail', Thumbnail)
|
||||
|
||||
Once a spec is registered with a unique name, you can start to take advantage of
|
||||
ImageKit's powerful utilities to automatically generate images for you...
|
||||
|
||||
.. note:: You might be wondering why we bother with the id string instead of
|
||||
just passing the spec itself. The reason is that these ids allow users to
|
||||
easily override specs defined in third party apps. That way, it doesn't
|
||||
matter if "django-badblog" says its thumbnails are 200x200, you can just
|
||||
register your own spec (using the same id the app uses) and have whatever
|
||||
size thumbnails you want.
|
||||
|
||||
|
||||
In Templates
|
||||
^^^^^^^^^^^^
|
||||
|
||||
One utility ImageKit provides for processing images is a template tag:
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
{% load imagekit %}
|
||||
|
||||
{% spec 'myapp:fancy_thumbnail' source_image alt='A picture of me' %}
|
||||
|
||||
Output:
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<img src="/static/CACHE/ik/982d5af84cddddfd0fbf70892b4431e4.jpg" width="100" height="50" alt="A picture of me" />
|
||||
|
||||
Not generating HTML image tags? No problem. The tag also functions as an
|
||||
assignment tag, providing access to the underlying file object:
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
{% load imagekit %}
|
||||
|
||||
{% spec 'myapp:fancy_thumbnail' source_image as th %}
|
||||
<a href="{{ th.url }}">Click to download a cool {{ th.width }} x {{ th.height }} image!</a>
|
||||
|
||||
|
||||
In Models
|
||||
^^^^^^^^^
|
||||
|
||||
Specs can also be used to add ``ImageField``-like fields that expose the result
|
||||
of applying a spec to another one of your model's fields:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
|
@ -39,73 +119,111 @@ of a model class:
|
|||
from imagekit.models import ImageSpecField
|
||||
|
||||
class Photo(models.Model):
|
||||
original_image = models.ImageField(upload_to='photos')
|
||||
formatted_image = ImageSpecField(image_field='original_image', format='JPEG',
|
||||
options={'quality': 90})
|
||||
|
||||
Accessing the spec through a model instance will create the image and return
|
||||
an ImageFile-like object (just like with a normal
|
||||
``django.db.models.ImageField``):
|
||||
|
||||
.. code-block:: python
|
||||
avatar = models.ImageField(upload_to='avatars')
|
||||
avatar_thumbnail = ImageSpecField(id='myapp:fancy_thumbnail', image_field='avatar')
|
||||
|
||||
photo = Photo.objects.all()[0]
|
||||
photo.original_image.url # > '/media/photos/birthday.tiff'
|
||||
photo.formatted_image.url # > '/media/cache/photos/birthday_formatted_image.jpeg'
|
||||
print photo.avatar_thumbnail.url # > /static/CACHE/ik/982d5af84cddddfd0fbf70892b4431e4.jpg
|
||||
print photo.avatar_thumbnail.width # > 100
|
||||
|
||||
Check out ``imagekit.models.ImageSpecField`` for more information.
|
||||
|
||||
If you only want to save the processed image (without maintaining the original),
|
||||
you can use a ``ProcessedImageField``:
|
||||
Since defining a spec, registering it, and using it in a single model field is
|
||||
such a common usage, ImakeKit provides a shortcut that allow you to skip
|
||||
writing a subclass of ``ImageSpec``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from django.db import models
|
||||
from imagekit.models.fields import ProcessedImageField
|
||||
from imagekit.models import ImageSpecField
|
||||
from imagekit.processors import ResizeToFill
|
||||
|
||||
class Photo(models.Model):
|
||||
processed_image = ProcessedImageField(format='JPEG', options={'quality': 90})
|
||||
avatar = models.ImageField(upload_to='avatars')
|
||||
avatar_thumbnail = ImageSpecField(processors=[ResizeToFill(100, 50)],
|
||||
format='JPEG',
|
||||
options={'quality': 60},
|
||||
image_field='avatar')
|
||||
|
||||
See the class documentation for details.
|
||||
photo = Photo.objects.all()[0]
|
||||
print photo.avatar_thumbnail.url # > /static/CACHE/ik/982d5af84cddddfd0fbf70892b4431e4.jpg
|
||||
print photo.avatar_thumbnail.width # > 100
|
||||
|
||||
This has the exact same behavior as before, but the spec definition is inlined.
|
||||
Since no ``id`` is provided, one is automatically generated based on the app
|
||||
name, model, and field.
|
||||
|
||||
Specs can also be used in models to add ``ImageField``-like fields that process
|
||||
a user-provided image without saving the original:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from django.db import models
|
||||
from imagekit.models import ProcessedImageField
|
||||
|
||||
class Photo(models.Model):
|
||||
avatar_thumbnail = ProcessedImageField(spec_id='myapp:fancy_thumbnail',
|
||||
upload_to='avatars')
|
||||
|
||||
photo = Photo.objects.all()[0]
|
||||
print photo.avatar_thumbnail.url # > /static/avatars/MY-avatar_3.jpg
|
||||
print photo.avatar_thumbnail.width # > 100
|
||||
|
||||
Like with ``ImageSpecField``, the ``ProcessedImageField`` constructor also
|
||||
has a shortcut version that allows you to inline spec definitions.
|
||||
|
||||
|
||||
In Forms
|
||||
^^^^^^^^
|
||||
|
||||
In addition to the model field above, there's also a form field version of the
|
||||
``ProcessedImageField`` class. The functionality is basically the same (it
|
||||
processes an image once and saves the result), but it's used in a form class:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from django import forms
|
||||
from imagekit.forms import ProcessedImageField
|
||||
|
||||
class AvatarForm(forms.Form):
|
||||
avatar_thumbnail = ProcessedImageField(spec_id='myapp:fancy_thumbnail')
|
||||
|
||||
The benefit of using ``imagekit.forms.ProcessedImageField`` (as opposed to
|
||||
``imagekit.models.ProcessedImageField`` above) is that it keeps the logic for
|
||||
creating the image outside of your model (in which you would use a normal
|
||||
Django ``ImageField``). You can even create multiple forms, each with their own
|
||||
``ProcessedImageField``, that all store their results in the same image field.
|
||||
|
||||
As with the model field classes, ``imagekit.forms.ProcessedImageField`` also
|
||||
has a shortcut version that allows you to inline spec definitions.
|
||||
|
||||
|
||||
Processors
|
||||
----------
|
||||
|
||||
The real power of ImageKit comes from processors. Processors take an image, do
|
||||
something to it, and return the result. By providing a list of processors to
|
||||
your spec, you can expose different versions of the original image:
|
||||
So far, we've only seen one processor: ``imagekit.processors.ResizeToFill``. But
|
||||
ImageKit is capable of far more than just resizing images, and that power comes
|
||||
from its processors.
|
||||
|
||||
Processors take a PIL image object, do something to it, and return a new one.
|
||||
A spec can make use of as many processors as you'd like, which will all be run
|
||||
in order.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from django.db import models
|
||||
from imagekit.models import ImageSpecField
|
||||
from imagekit.processors import ResizeToFill, Adjust
|
||||
from imagekit import ImageSpec
|
||||
from imagekit.processors import TrimBorderColor, Adjust
|
||||
|
||||
class Photo(models.Model):
|
||||
original_image = models.ImageField(upload_to='photos')
|
||||
thumbnail = ImageSpecField([Adjust(contrast=1.2, sharpness=1.1),
|
||||
ResizeToFill(50, 50)], image_field='original_image',
|
||||
format='JPEG', options={'quality': 90})
|
||||
|
||||
The ``thumbnail`` property will now return a cropped image:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
photo = Photo.objects.all()[0]
|
||||
photo.thumbnail.url # > '/media/cache/photos/birthday_thumbnail.jpeg'
|
||||
photo.thumbnail.width # > 50
|
||||
photo.original_image.width # > 1000
|
||||
|
||||
The original image is not modified; ``thumbnail`` is a new file that is the
|
||||
result of running the ``imagekit.processors.ResizeToFill`` processor on the
|
||||
original. (If you only need to save the processed image, and not the original,
|
||||
pass processors to a ``ProcessedImageField`` instead of an ``ImageSpecField``.)
|
||||
class MySpec(ImageSpec):
|
||||
processors = [
|
||||
TrimBorderColor(),
|
||||
Adjust(contrast=1.2, sharpness=1.1),
|
||||
]
|
||||
format = 'JPEG'
|
||||
options = {'quality': 60}
|
||||
|
||||
The ``imagekit.processors`` module contains processors for many common
|
||||
image manipulations, like resizing, rotating, and color adjustments. However,
|
||||
if they aren't up to the task, you can create your own. All you have to do is
|
||||
implement a ``process()`` method:
|
||||
define a class that implements a ``process()`` method:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
|
@ -114,10 +232,23 @@ implement a ``process()`` method:
|
|||
# Code for adding the watermark goes here.
|
||||
return image
|
||||
|
||||
class Photo(models.Model):
|
||||
original_image = models.ImageField(upload_to='photos')
|
||||
watermarked_image = ImageSpecField([Watermark()], image_field='original_image',
|
||||
format='JPEG', options={'quality': 90})
|
||||
That's all there is to it! To use your fancy new custom processor, just include
|
||||
it in your spec's ``processors`` list:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from imagekit import ImageSpec
|
||||
from imagekit.processors import TrimBorderColor, Adjust
|
||||
from myapp.processors import Watermark
|
||||
|
||||
class MySpec(ImageSpec):
|
||||
processors = [
|
||||
TrimBorderColor(),
|
||||
Adjust(contrast=1.2, sharpness=1.1),
|
||||
Watermark(),
|
||||
]
|
||||
format = 'JPEG'
|
||||
options = {'quality': 60}
|
||||
|
||||
|
||||
Admin
|
||||
|
|
@ -134,12 +265,10 @@ Django admin classes:
|
|||
from imagekit.admin import AdminThumbnail
|
||||
from .models import Photo
|
||||
|
||||
|
||||
class PhotoAdmin(admin.ModelAdmin):
|
||||
list_display = ('__str__', 'admin_thumbnail')
|
||||
admin_thumbnail = AdminThumbnail(image_field='thumbnail')
|
||||
|
||||
|
||||
admin.site.register(Photo, PhotoAdmin)
|
||||
|
||||
AdminThumbnail can even use a custom template. For more information, see
|
||||
|
|
@ -148,40 +277,6 @@ AdminThumbnail can even use a custom template. For more information, see
|
|||
.. _`Django admin change list`: https://docs.djangoproject.com/en/dev/intro/tutorial02/#customize-the-admin-change-list
|
||||
|
||||
|
||||
Image Cache Backends
|
||||
--------------------
|
||||
|
||||
Whenever you access properties like ``url``, ``width`` and ``height`` of an
|
||||
``ImageSpecField``, its cached image is validated; whenever you save a new image
|
||||
to the ``ImageField`` your spec uses as a source, the spec image is invalidated.
|
||||
The default way to validate a cache image is to check to see if the file exists
|
||||
and, if not, generate a new one; the default way to invalidate the cache is to
|
||||
delete the image. This is a very simple and straightforward way to handle cache
|
||||
validation, but it has its drawbacks—for example, checking to see if the image
|
||||
exists means frequently hitting the storage backend.
|
||||
|
||||
Because of this, ImageKit allows you to define custom image cache backends. To
|
||||
be a valid image cache backend, a class must implement three methods:
|
||||
``validate``, ``invalidate``, and ``clear`` (which is called when the image is
|
||||
no longer needed in any form, i.e. the model is deleted). Each of these methods
|
||||
must accept a file object, but the internals are up to you. For example, you
|
||||
could store the state (valid, invalid) of the cache in a database to avoid
|
||||
filesystem access. You can then specify your image cache backend on a per-field
|
||||
basis:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class Photo(models.Model):
|
||||
...
|
||||
thumbnail = ImageSpecField(..., image_cache_backend=MyImageCacheBackend())
|
||||
|
||||
Or in your ``settings.py`` file if you want to use it as the default:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
IMAGEKIT_DEFAULT_IMAGE_CACHE_BACKEND = 'path.to.MyImageCacheBackend'
|
||||
|
||||
|
||||
Community
|
||||
---------
|
||||
|
||||
|
|
@ -199,7 +294,3 @@ even Django—to contribute either: ImageKit's processors are standalone classes
|
|||
that are completely separate from the more intimidating internals of Django's
|
||||
ORM. If you've written a processor that you think might be useful to other
|
||||
people, open a pull request so we can take a look!
|
||||
|
||||
ImageKit's image cache backends are also fairly isolated from the ImageKit guts.
|
||||
If you've fine-tuned one to work perfectly for a popular file storage backend,
|
||||
let us take a look! Maybe other people could use it.
|
||||
|
|
|
|||
Loading…
Reference in a new issue