mirror of
https://github.com/Hopiu/django-imagekit.git
synced 2026-03-17 05:40:25 +00:00
_imgfield is now a property of ImageSpec
Moved _imgfield from ImageModel to ImageSpec. Theoretically, this will allow you to have specs that use different image fields on the same model.
This commit is contained in:
parent
5e00de5204
commit
4c78f2d24c
4 changed files with 47 additions and 36 deletions
|
|
@ -70,7 +70,7 @@ class ImageModel(models.Model):
|
|||
abstract = True
|
||||
|
||||
def admin_thumbnail_view(self):
|
||||
if not self._imgfield:
|
||||
if not self._imgfields:
|
||||
return None
|
||||
prop = getattr(self, self._ik.admin_thumbnail_property, None)
|
||||
if prop is None:
|
||||
|
|
@ -82,17 +82,13 @@ class ImageModel(models.Model):
|
|||
(escape(self.get_absolute_url()), escape(prop.url))
|
||||
else:
|
||||
return u'<a href="%s"><img src="%s"></a>' % \
|
||||
(escape(self._imgfield.url), escape(prop.url))
|
||||
(escape(self._get_imgfield(self).url), escape(prop.url))
|
||||
admin_thumbnail_view.short_description = _('Thumbnail')
|
||||
admin_thumbnail_view.allow_tags = True
|
||||
|
||||
class IKOptions:
|
||||
pass
|
||||
|
||||
@property
|
||||
def _imgfield(self):
|
||||
return getattr(self, self._ik.image_field)
|
||||
|
||||
def _clear_cache(self):
|
||||
for spec in self._ik.specs:
|
||||
prop = getattr(self, spec.name())
|
||||
|
|
@ -105,14 +101,20 @@ class ImageModel(models.Model):
|
|||
prop._create()
|
||||
|
||||
def save_image(self, name, image, save=True, replace=True):
|
||||
if self._imgfield and replace:
|
||||
self._imgfield.delete(save=False)
|
||||
if hasattr(image, 'read'):
|
||||
data = image.read()
|
||||
else:
|
||||
data = image
|
||||
content = ContentFile(data)
|
||||
self._imgfield.save(name, content, save)
|
||||
imgfields = self._imgfields
|
||||
for imgfield in imgfields:
|
||||
if imgfield and replace:
|
||||
imgfield.delete(save=False)
|
||||
if hasattr(image, 'read'):
|
||||
data = image.read()
|
||||
else:
|
||||
data = image
|
||||
content = ContentFile(data)
|
||||
imgfield.save(name, content, save)
|
||||
|
||||
@property
|
||||
def _imgfields(self):
|
||||
return set([spec._get_imgfield(self) for spec in self._ik.specs])
|
||||
|
||||
def save(self, clear_cache=True, *args, **kwargs):
|
||||
super(ImageModel, self).save(*args, **kwargs)
|
||||
|
|
@ -121,10 +123,11 @@ class ImageModel(models.Model):
|
|||
if is_new_object:
|
||||
clear_cache = False
|
||||
|
||||
if self._imgfield:
|
||||
imgfields = self._imgfields
|
||||
for imgfield in imgfields:
|
||||
spec = self._ik.preprocessor_spec
|
||||
if spec is not None:
|
||||
newfile = self._imgfield.storage.open(str(self._imgfield))
|
||||
newfile = imgfield.storage.open(str(imgfield))
|
||||
img = Image.open(newfile)
|
||||
img, format = spec.process(img, self)
|
||||
if format != 'JPEG':
|
||||
|
|
@ -135,10 +138,10 @@ class ImageModel(models.Model):
|
|||
optimize=True)
|
||||
content = ContentFile(imgfile.read())
|
||||
newfile.close()
|
||||
name = str(self._imgfield)
|
||||
self._imgfield.storage.delete(name)
|
||||
self._imgfield.storage.save(name, content)
|
||||
if self._imgfield:
|
||||
name = str(imgfield)
|
||||
imgfield.storage.delete(name)
|
||||
imgfield.storage.save(name, content)
|
||||
if self._imgfields:
|
||||
if clear_cache:
|
||||
self._clear_cache()
|
||||
self._pre_cache()
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ class Options(object):
|
|||
""" Class handling per-model imagekit options
|
||||
|
||||
"""
|
||||
|
||||
|
||||
admin_thumbnail_property = 'admin_thumbnail'
|
||||
"""The name of the spec to be used by the admin_thumbnail_view"""
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ from imagekit.lib import *
|
|||
class ImageProcessor(object):
|
||||
""" Base image processor class """
|
||||
|
||||
def process(self, img, fmt, obj):
|
||||
def process(self, img, fmt, obj, spec):
|
||||
return img, fmt
|
||||
|
||||
|
||||
|
|
@ -23,7 +23,7 @@ class Adjust(ImageProcessor):
|
|||
self.contrast = contrast
|
||||
self.sharpness = sharpness
|
||||
|
||||
def process(self, img, fmt, obj):
|
||||
def process(self, img, fmt, obj, spec):
|
||||
img = img.convert('RGB')
|
||||
for name in ['Color', 'Brightness', 'Contrast', 'Sharpness']:
|
||||
factor = getattr(self, name.lower())
|
||||
|
|
@ -39,7 +39,7 @@ class Format(ImageProcessor):
|
|||
format = 'JPEG'
|
||||
extension = 'jpg'
|
||||
|
||||
def process(self, img, fmt, obj):
|
||||
def process(self, img, fmt, obj, spec):
|
||||
return img, self.format
|
||||
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ class Reflection(ImageProcessor):
|
|||
size = 0.0
|
||||
opacity = 0.6
|
||||
|
||||
def process(self, img, fmt, obj):
|
||||
def process(self, img, fmt, obj, spec):
|
||||
# convert bgcolor string to rgb value
|
||||
background_color = ImageColor.getrgb(self.background_color)
|
||||
# handle palleted images
|
||||
|
|
@ -102,7 +102,7 @@ class _Resize(ImageProcessor):
|
|||
if upscale is not None:
|
||||
self.upscale = upscale
|
||||
|
||||
def process(self, img, fmt, obj):
|
||||
def process(self, img, fmt, obj, spec):
|
||||
cur_width, cur_height = img.size
|
||||
if self.crop:
|
||||
crop_horz = getattr(obj, obj._ik.crop_horz_field, 1)
|
||||
|
|
@ -180,10 +180,10 @@ class Transpose(ImageProcessor):
|
|||
|
||||
method = 'auto'
|
||||
|
||||
def process(self, img, fmt, obj):
|
||||
def process(self, img, fmt, obj, spec):
|
||||
if self.method == 'auto':
|
||||
try:
|
||||
orientation = Image.open(obj._imgfield.file)._getexif()[0x0112]
|
||||
orientation = Image.open(spec._get_imgfield(obj).file)._getexif()[0x0112]
|
||||
ops = self.EXIF_ORIENTATION_STEPS[orientation]
|
||||
except:
|
||||
ops = []
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ from django.core.files.base import ContentFile
|
|||
|
||||
class ImageSpec(object):
|
||||
|
||||
image_field = 'original_image' # TODO: Get rid of this. It can be specified in a SpecDefaults nested class.
|
||||
processors = []
|
||||
pre_cache = False
|
||||
quality = 70
|
||||
|
|
@ -25,11 +26,14 @@ class ImageSpec(object):
|
|||
self.processors = processors
|
||||
self.__dict__.update(kwargs)
|
||||
|
||||
def _get_imgfield(self, obj):
|
||||
return getattr(obj, self.image_field)
|
||||
|
||||
def process(self, image, obj):
|
||||
fmt = image.format
|
||||
img = image.copy()
|
||||
for proc in self.processors:
|
||||
img, fmt = proc.process(img, fmt, obj)
|
||||
img, fmt = proc.process(img, fmt, obj, self)
|
||||
img.format = fmt
|
||||
return img, fmt
|
||||
|
||||
|
|
@ -52,13 +56,17 @@ class Accessor(object):
|
|||
optimize=True)
|
||||
return imgfile
|
||||
|
||||
@property
|
||||
def _imgfield(self):
|
||||
return self.spec._get_imgfield(self._obj)
|
||||
|
||||
def _create(self):
|
||||
if self._obj._imgfield:
|
||||
if self._imgfield:
|
||||
if self._exists():
|
||||
return
|
||||
# process the original image file
|
||||
try:
|
||||
fp = self._obj._imgfield.storage.open(self._obj._imgfield.name)
|
||||
fp = self._imgfield.storage.open(self._imgfield.name)
|
||||
except IOError:
|
||||
return
|
||||
fp.seek(0)
|
||||
|
|
@ -69,20 +77,20 @@ class Accessor(object):
|
|||
self._storage.save(self.name, content)
|
||||
|
||||
def _delete(self):
|
||||
if self._obj._imgfield:
|
||||
if self._imgfield:
|
||||
try:
|
||||
self._storage.delete(self.name)
|
||||
except (NotImplementedError, IOError):
|
||||
return
|
||||
|
||||
def _exists(self):
|
||||
if self._obj._imgfield:
|
||||
if self._imgfield:
|
||||
return self._storage.exists(self.name)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
if self._obj._imgfield.name:
|
||||
filepath, basename = os.path.split(self._obj._imgfield.name)
|
||||
if self._imgfield.name:
|
||||
filepath, basename = os.path.split(self._imgfield.name)
|
||||
filename, extension = os.path.splitext(basename)
|
||||
for processor in self.spec.processors:
|
||||
if isinstance(processor, processors.Format):
|
||||
|
|
@ -107,7 +115,7 @@ class Accessor(object):
|
|||
|
||||
@property
|
||||
def _storage(self):
|
||||
return getattr(self._obj._ik, 'storage', self._obj._imgfield.storage)
|
||||
return getattr(self._obj._ik, 'storage', self._imgfield.storage)
|
||||
|
||||
@property
|
||||
def url(self):
|
||||
|
|
|
|||
Loading…
Reference in a new issue