mirror of
https://github.com/Hopiu/django-imagekit.git
synced 2026-03-16 21:30:23 +00:00
Rename ImageSpec to ImageSpecField
The ImageSpec class remains for now, but using it throws deprecation warnings.
This commit is contained in:
parent
c2a4d01b7c
commit
c3ef5172c3
5 changed files with 42 additions and 33 deletions
12
README.rst
12
README.rst
|
|
@ -29,11 +29,11 @@ Much like ``django.db.models.ImageField``, Specs are defined as properties
|
|||
of a model class::
|
||||
|
||||
from django.db import models
|
||||
from imagekit.models import ImageSpec
|
||||
from imagekit.models import ImageSpecField
|
||||
|
||||
class Photo(models.Model):
|
||||
original_image = models.ImageField(upload_to='photos')
|
||||
formatted_image = ImageSpec(image_field='original_image', format='JPEG',
|
||||
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
|
||||
|
|
@ -44,7 +44,7 @@ an ImageFile-like object (just like with a normal
|
|||
photo.original_image.url # > '/media/photos/birthday.tiff'
|
||||
photo.formatted_image.url # > '/media/cache/photos/birthday_formatted_image.jpeg'
|
||||
|
||||
Check out ``imagekit.models.ImageSpec`` for more information.
|
||||
Check out ``imagekit.models.ImageSpecField`` for more information.
|
||||
|
||||
|
||||
Processors
|
||||
|
|
@ -55,12 +55,12 @@ 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::
|
||||
|
||||
from django.db import models
|
||||
from imagekit.models import ImageSpec
|
||||
from imagekit.models import ImageSpecField
|
||||
from imagekit.processors import resize, Adjust
|
||||
|
||||
class Photo(models.Model):
|
||||
original_image = models.ImageField(upload_to='photos')
|
||||
thumbnail = ImageSpec([Adjust(contrast=1.2, sharpness=1.1),
|
||||
thumbnail = ImageSpecField([Adjust(contrast=1.2, sharpness=1.1),
|
||||
resize.Crop(50, 50)], image_field='original_image',
|
||||
format='JPEG', options={'quality': 90})
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ implement a ``process()`` method::
|
|||
|
||||
class Photo(models.Model):
|
||||
original_image = models.ImageField(upload_to='photos')
|
||||
watermarked_image = ImageSpec([Watermark()], image_field='original_image',
|
||||
watermarked_image = ImageSpecField([Watermark()], image_field='original_image',
|
||||
format='JPEG', options={'quality': 90})
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class AdminThumbnail(object):
|
|||
|
||||
def __init__(self, image_field, template=None):
|
||||
"""
|
||||
:param image_field: The name of the ImageField or ImageSpec on the
|
||||
:param image_field: The name of the ImageField or ImageSpecField on the
|
||||
model to use for the thumbnail.
|
||||
:param template: The template with which to render the thumbnail
|
||||
|
||||
|
|
|
|||
|
|
@ -12,9 +12,10 @@ from imagekit.utils import img_to_fobj, get_spec_files, open_image, \
|
|||
format_to_extension, extension_to_format, UnknownFormatError, \
|
||||
UnknownExtensionError
|
||||
from imagekit.processors import ProcessorPipeline, AutoConvert
|
||||
import warnings
|
||||
|
||||
|
||||
class _ImageSpecMixin(object):
|
||||
class _ImageSpecFieldMixin(object):
|
||||
def __init__(self, processors=None, format=None, options={},
|
||||
autoconvert=True):
|
||||
self.processors = processors
|
||||
|
|
@ -30,9 +31,9 @@ class _ImageSpecMixin(object):
|
|||
return processors.process(image.copy())
|
||||
|
||||
|
||||
class ImageSpec(_ImageSpecMixin):
|
||||
class ImageSpecField(_ImageSpecFieldMixin):
|
||||
"""
|
||||
The heart and soul of the ImageKit library, ImageSpec allows you to add
|
||||
The heart and soul of the ImageKit library, ImageSpecField allows you to add
|
||||
variants of uploaded images to your models.
|
||||
|
||||
"""
|
||||
|
|
@ -44,7 +45,7 @@ class ImageSpec(_ImageSpecMixin):
|
|||
"""
|
||||
:param processors: A list of processors to run on the original image.
|
||||
:param format: The format of the output file. If not provided,
|
||||
ImageSpec will try to guess the appropriate format based on the
|
||||
ImageSpecField will try to guess the appropriate format based on the
|
||||
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
|
||||
|
|
@ -77,7 +78,7 @@ class ImageSpec(_ImageSpecMixin):
|
|||
|
||||
"""
|
||||
|
||||
_ImageSpecMixin.__init__(self, processors, format=format,
|
||||
_ImageSpecFieldMixin.__init__(self, processors, format=format,
|
||||
options=options, autoconvert=autoconvert)
|
||||
self.image_field = image_field
|
||||
self.pre_cache = pre_cache
|
||||
|
|
@ -85,7 +86,7 @@ class ImageSpec(_ImageSpecMixin):
|
|||
self.cache_to = cache_to
|
||||
|
||||
def contribute_to_class(self, cls, name):
|
||||
setattr(cls, name, _ImageSpecDescriptor(self, name))
|
||||
setattr(cls, name, _ImageSpecFieldDescriptor(self, name))
|
||||
try:
|
||||
ik = getattr(cls, '_ik')
|
||||
except AttributeError:
|
||||
|
|
@ -101,6 +102,13 @@ class ImageSpec(_ImageSpecMixin):
|
|||
dispatch_uid='%s.delete' % uid)
|
||||
|
||||
|
||||
class ImageSpec(ImageSpecField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
warnings.warn('ImageSpec has been renamed to ImageSpecField. Please'
|
||||
' use that instead.', DeprecationWarning)
|
||||
super(ImageSpec, self).__init__(*args, **kwargs)
|
||||
|
||||
|
||||
def _get_suggested_extension(name, format):
|
||||
original_extension = os.path.splitext(name)[1]
|
||||
try:
|
||||
|
|
@ -124,7 +132,7 @@ def _get_suggested_extension(name, format):
|
|||
return extension
|
||||
|
||||
|
||||
class _ImageSpecFileMixin(object):
|
||||
class _ImageSpecFieldFileMixin(object):
|
||||
def _process_content(self, filename, content):
|
||||
img = open_image(content)
|
||||
original_format = img.format
|
||||
|
|
@ -156,7 +164,7 @@ class _ImageSpecFileMixin(object):
|
|||
return img, content
|
||||
|
||||
|
||||
class ImageSpecFile(_ImageSpecFileMixin, ImageFieldFile):
|
||||
class ImageSpecFieldFile(_ImageSpecFieldFileMixin, ImageFieldFile):
|
||||
def __init__(self, instance, field, attname):
|
||||
ImageFieldFile.__init__(self, instance, field, None)
|
||||
self.attname = attname
|
||||
|
|
@ -173,12 +181,12 @@ class ImageSpecFile(_ImageSpecFileMixin, ImageFieldFile):
|
|||
isinstance(f, models.ImageField)]
|
||||
if len(image_fields) == 0:
|
||||
raise Exception('%s does not define any ImageFields, so your' \
|
||||
' %s ImageSpec has no image to act on.' % \
|
||||
' %s ImageSpecField has no image to act on.' % \
|
||||
(self.instance.__class__.__name__, self.attname))
|
||||
elif len(image_fields) > 1:
|
||||
raise Exception('%s defines multiple ImageFields, but you' \
|
||||
' have not specified an image_field for your %s' \
|
||||
' ImageSpec.' % (self.instance.__class__.__name__,
|
||||
' ImageSpecField.' % (self.instance.__class__.__name__,
|
||||
self.attname))
|
||||
else:
|
||||
field_file = image_fields[0]
|
||||
|
|
@ -275,7 +283,7 @@ class ImageSpecFile(_ImageSpecFileMixin, ImageFieldFile):
|
|||
def name(self):
|
||||
"""
|
||||
Specifies the filename that the cached image will use. The user can
|
||||
control this by providing a `cache_to` method to the ImageSpec.
|
||||
control this by providing a `cache_to` method to the ImageSpecField.
|
||||
|
||||
"""
|
||||
name = getattr(self, '_name', None)
|
||||
|
|
@ -303,12 +311,12 @@ class ImageSpecFile(_ImageSpecFileMixin, ImageFieldFile):
|
|||
def name(self, value):
|
||||
# TODO: Figure out a better way to handle this. We really don't want
|
||||
# to allow anybody to set the name, but ``File.__init__`` (which is
|
||||
# called by ``ImageSpecFile.__init__``) does, so we have to allow it
|
||||
# at least that one time.
|
||||
# called by ``ImageSpecFieldFile.__init__``) does, so we have to allow
|
||||
# it at least that one time.
|
||||
pass
|
||||
|
||||
|
||||
class _ImageSpecDescriptor(object):
|
||||
class _ImageSpecFieldDescriptor(object):
|
||||
def __init__(self, field, attname):
|
||||
self.attname = attname
|
||||
self.field = field
|
||||
|
|
@ -317,7 +325,8 @@ class _ImageSpecDescriptor(object):
|
|||
if instance is None:
|
||||
return self.field
|
||||
else:
|
||||
img_spec_file = ImageSpecFile(instance, self.field, self.attname)
|
||||
img_spec_file = ImageSpecFieldFile(instance, self.field,
|
||||
self.attname)
|
||||
setattr(instance, self.attname, img_spec_file)
|
||||
return img_spec_file
|
||||
|
||||
|
|
@ -340,14 +349,14 @@ def _post_delete_handler(sender, instance=None, **kwargs):
|
|||
spec_file.delete(save=False)
|
||||
|
||||
|
||||
class ProcessedImageFieldFile(ImageFieldFile, _ImageSpecFileMixin):
|
||||
class ProcessedImageFieldFile(ImageFieldFile, _ImageSpecFieldFileMixin):
|
||||
def save(self, name, content, save=True):
|
||||
new_filename = self.field.generate_filename(self.instance, name)
|
||||
img, content = self._process_content(new_filename, content)
|
||||
return super(ProcessedImageFieldFile, self).save(name, content, save)
|
||||
|
||||
|
||||
class ProcessedImageField(models.ImageField, _ImageSpecMixin):
|
||||
class ProcessedImageField(models.ImageField, _ImageSpecFieldMixin):
|
||||
"""
|
||||
ProcessedImageField is an ImageField that runs processors on the uploaded
|
||||
image *before* saving it to storage. This is in contrast to specs, which
|
||||
|
|
@ -365,14 +374,14 @@ class ProcessedImageField(models.ImageField, _ImageSpecMixin):
|
|||
The ProcessedImageField constructor accepts all of the arguments that
|
||||
the :class:`django.db.models.ImageField` constructor accepts, as well
|
||||
as the ``processors``, ``format``, and ``options`` arguments of
|
||||
:class:`imagekit.models.ImageSpec`.
|
||||
:class:`imagekit.models.ImageSpecField`.
|
||||
|
||||
"""
|
||||
if 'quality' in kwargs:
|
||||
raise Exception('The "quality" keyword argument has been'
|
||||
""" deprecated. Use `options={'quality': %s}` instead.""" \
|
||||
% kwargs['quality'])
|
||||
_ImageSpecMixin.__init__(self, processors, format=format,
|
||||
_ImageSpecFieldMixin.__init__(self, processors, format=format,
|
||||
options=options, autoconvert=autoconvert)
|
||||
models.ImageField.__init__(self, verbose_name, name, width_field,
|
||||
height_field, **kwargs)
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ class Transpose(object):
|
|||
class AutoConvert(object):
|
||||
"""A processor that does some common-sense conversions based on the target
|
||||
format. This includes things like preserving transparency and quantizing.
|
||||
This processors is used automatically by ``ImageSpec`` and
|
||||
This processors is used automatically by ``ImageSpecField`` and
|
||||
``ProcessedImageField`` immediately before saving the image unless you
|
||||
specify ``autoconvert=False``.
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ from django.test import TestCase
|
|||
|
||||
from imagekit import utils
|
||||
from imagekit.lib import Image
|
||||
from imagekit.models import ImageSpec
|
||||
from imagekit.models import ImageSpecField
|
||||
from imagekit.processors import Adjust
|
||||
from imagekit.processors.resize import Crop
|
||||
from imagekit.processors.crop import SmartCrop
|
||||
|
|
@ -18,13 +18,13 @@ from imagekit.processors.crop import SmartCrop
|
|||
class Photo(models.Model):
|
||||
original_image = models.ImageField(upload_to='photos')
|
||||
|
||||
thumbnail = ImageSpec([Adjust(contrast=1.2, sharpness=1.1), Crop(50, 50)],
|
||||
image_field='original_image', format='JPEG',
|
||||
thumbnail = ImageSpecField([Adjust(contrast=1.2, sharpness=1.1),
|
||||
Crop(50, 50)], image_field='original_image', format='JPEG',
|
||||
options={'quality': 90})
|
||||
|
||||
smartcropped_thumbnail = ImageSpec([Adjust(contrast=1.2, sharpness=1.1), SmartCrop(50, 50)],
|
||||
image_field='original_image', format='JPEG',
|
||||
options={'quality': 90})
|
||||
smartcropped_thumbnail = ImageSpecField([Adjust(contrast=1.2,
|
||||
sharpness=1.1), SmartCrop(50, 50)], image_field='original_image',
|
||||
format='JPEG', options={'quality': 90})
|
||||
|
||||
|
||||
class IKTest(TestCase):
|
||||
|
|
|
|||
Loading…
Reference in a new issue