django-imagekit/imagekit/models/fields/__init__.py

131 lines
5.4 KiB
Python
Raw Normal View History

2012-02-14 16:34:51 +00:00
import os
2008-12-28 21:48:21 +00:00
from django.db import models
2012-02-14 02:44:29 +00:00
from ...imagecache import get_default_image_cache_backend
from ...generators import SpecFileGenerator
from .files import ImageSpecFieldFile, ProcessedImageFieldFile
from ..receivers import configure_receivers
from .utils import ImageSpecFileDescriptor, ImageKitMeta, BoundImageKitMeta
from ...utils import suggest_extension
configure_receivers()
2012-02-12 01:11:56 +00:00
class ImageSpecField(object):
2011-10-31 14:12:03 +00:00
"""
The heart and soul of the ImageKit library, ImageSpecField allows you to add
2011-09-26 00:38:43 +00:00
variants of uploaded images to your models.
2009-12-19 16:01:54 +00:00
"""
2012-04-10 01:25:46 +00:00
def __init__(self, processors=None, format=None, options=None,
image_field=None, pre_cache=None, storage=None, autoconvert=True,
image_cache_backend=None):
2011-09-26 00:38:43 +00:00
"""
:param processors: A list of processors to run on the original image.
2011-10-31 14:12:03 +00:00
:param format: The format of the output file. If not provided,
ImageSpecField will try to guess the appropriate format based on the
2011-10-31 14:12:03 +00:00
extension of the filename and the format of the input image.
:param options: A dictionary that will be passed to PIL's
``Image.save()`` method as keyword arguments. Valid options vary
between formats, but some examples include ``quality``,
``optimize``, and ``progressive`` for JPEGs. See the PIL
documentation for others.
2011-09-26 00:38:43 +00:00
:param image_field: The name of the model property that contains the
2011-10-31 14:12:03 +00:00
original image.
2011-09-26 00:38:43 +00:00
:param storage: A Django storage system to use to save the generated
2011-10-31 14:12:03 +00:00
image.
:param autoconvert: Specifies whether automatic conversion using
``prepare_image()`` should be performed prior to saving.
:param image_cache_backend: An object responsible for managing the state
of cached files. Defaults to an instance of
IMAGEKIT_DEFAULT_IMAGE_CACHE_BACKEND
2011-09-26 00:38:43 +00:00
"""
2011-09-21 15:37:29 +00:00
if pre_cache is not None:
raise Exception('The pre_cache argument has been removed in favor'
' of cache state backends.')
2012-02-12 04:22:06 +00:00
# The generator accepts a callable value for processors, but it
# takes different arguments than the callable that ImageSpecField
# expects, so we create a partial application and pass that instead.
# TODO: Should we change the signatures to match? Even if `instance` is not part of the signature, it's accessible through the source file object's instance property.
p = lambda file: processors(instance=file.instance, file=file) if \
callable(processors) else processors
self.generator = SpecFileGenerator(p, format=format, options=options,
2012-02-12 04:41:07 +00:00
autoconvert=autoconvert, storage=storage)
self.image_field = image_field
self.storage = storage
self.image_cache_backend = image_cache_backend or \
get_default_image_cache_backend()
2011-09-21 15:37:29 +00:00
def contribute_to_class(self, cls, name):
setattr(cls, name, ImageSpecFileDescriptor(self, name))
try:
# Make sure we don't modify an inherited ImageKitMeta instance
ik = cls.__dict__['ik']
except KeyError:
try:
base = getattr(cls, '_ik')
except AttributeError:
ik = ImageKitMeta()
else:
# Inherit all the spec fields.
ik = ImageKitMeta(base.spec_fields)
setattr(cls, '_ik', ik)
ik.spec_fields.append(name)
# Register the field with the image_cache_backend
try:
self.image_cache_backend.register_field(cls, self, name)
except AttributeError:
pass
2011-09-21 15:37:29 +00:00
2012-02-12 01:11:56 +00:00
class ProcessedImageField(models.ImageField):
2011-10-31 14:12:03 +00:00
"""
ProcessedImageField is an ImageField that runs processors on the uploaded
2011-09-26 00:38:43 +00:00
image *before* saving it to storage. This is in contrast to specs, which
maintain the original. Useful for coercing fileformats or keeping images
within a reasonable size.
"""
attr_class = ProcessedImageFieldFile
2012-04-10 01:25:46 +00:00
def __init__(self, processors=None, format=None, options=None,
verbose_name=None, name=None, width_field=None, height_field=None,
autoconvert=True, **kwargs):
2011-09-26 00:38:43 +00:00
"""
The ProcessedImageField constructor accepts all of the arguments that
2011-10-31 14:12:03 +00:00
the :class:`django.db.models.ImageField` constructor accepts, as well
as the ``processors``, ``format``, and ``options`` arguments of
:class:`imagekit.models.ImageSpecField`.
2011-09-26 00:38:43 +00:00
"""
if 'quality' in kwargs:
raise Exception('The "quality" keyword argument has been'
""" deprecated. Use `options={'quality': %s}` instead.""" \
% kwargs['quality'])
models.ImageField.__init__(self, verbose_name, name, width_field,
height_field, **kwargs)
2012-02-12 01:11:56 +00:00
self.generator = SpecFileGenerator(processors, format=format,
2012-02-12 01:20:11 +00:00
options=options, autoconvert=autoconvert)
def get_filename(self, filename):
2012-02-12 04:27:25 +00:00
filename = os.path.normpath(self.storage.get_valid_name(
os.path.basename(filename)))
name, ext = os.path.splitext(filename)
ext = suggest_extension(filename, self.generator.format)
2012-02-16 13:47:22 +00:00
return u'%s%s' % (name, ext)
try:
from south.modelsinspector import add_introspection_rules
except ImportError:
pass
else:
add_introspection_rules([], [r'^imagekit\.models\.fields\.ProcessedImageField$'])