mirror of
https://github.com/Hopiu/django-imagekit.git
synced 2026-03-17 13:50:24 +00:00
129 lines
4.4 KiB
Python
129 lines
4.4 KiB
Python
from django.db.models.fields.files import ImageField, ImageFieldFile
|
|
|
|
|
|
class ImageSpecFieldFile(ImageFieldFile):
|
|
def __init__(self, instance, field, attname):
|
|
super(ImageSpecFieldFile, self).__init__(instance, field, None)
|
|
self.attname = attname
|
|
|
|
def get_hash(self):
|
|
return self.field.spec.get_hash(self.source_file)
|
|
|
|
@property
|
|
def source_file(self):
|
|
field_name = getattr(self.field, 'image_field', None)
|
|
if field_name:
|
|
field_file = getattr(self.instance, field_name)
|
|
else:
|
|
image_fields = [getattr(self.instance, f.attname) for f in \
|
|
self.instance.__class__._meta.fields if \
|
|
isinstance(f, ImageField)]
|
|
if len(image_fields) == 0:
|
|
raise Exception('%s does not define any ImageFields, so your' \
|
|
' %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' \
|
|
' ImageSpecField.' % (self.instance.__class__.__name__,
|
|
self.attname))
|
|
else:
|
|
field_file = image_fields[0]
|
|
return field_file
|
|
|
|
def _require_file(self):
|
|
if not self.source_file:
|
|
raise ValueError("The '%s' attribute's image_field has no file associated with it." % self.attname)
|
|
self.field.spec.image_cache_strategy.invoke_callback('access', self)
|
|
|
|
def clear(self):
|
|
return self.field.spec.image_cache_backend.clear(self)
|
|
|
|
def invalidate(self):
|
|
return self.field.spec.image_cache_backend.invalidate(self)
|
|
|
|
def validate(self):
|
|
return self.field.spec.image_cache_backend.validate(self)
|
|
|
|
def generate(self, save=True):
|
|
"""
|
|
Generates a new image file by processing the source file and returns
|
|
the content of the result, ready for saving.
|
|
|
|
"""
|
|
return self.field.spec.generate_file(self.name, self.source_file,
|
|
save)
|
|
|
|
def delete(self, save=False):
|
|
"""
|
|
Pulled almost verbatim from ``ImageFieldFile.delete()`` and
|
|
``FieldFile.delete()`` but with the attempts to reset the instance
|
|
property removed.
|
|
|
|
"""
|
|
# Clear the image dimensions cache
|
|
if hasattr(self, '_dimensions_cache'):
|
|
del self._dimensions_cache
|
|
|
|
# Only close the file if it's already open, which we know by the
|
|
# presence of self._file.
|
|
if hasattr(self, '_file'):
|
|
self.close()
|
|
del self.file
|
|
|
|
if self.name and self.storage.exists(self.name):
|
|
try:
|
|
self.storage.delete(self.name)
|
|
except NotImplementedError:
|
|
pass
|
|
|
|
# Delete the filesize cache.
|
|
if hasattr(self, '_size'):
|
|
del self._size
|
|
self._committed = False
|
|
|
|
if save:
|
|
self.instance.save()
|
|
|
|
@property
|
|
def name(self):
|
|
"""
|
|
Specifies the filename that the cached image will use.
|
|
|
|
"""
|
|
return self.field.spec.generate_filename(self.source_file)
|
|
|
|
@name.setter
|
|
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 ``ImageSpecFieldFile.__init__``) does, so we have to allow
|
|
# it at least that one time.
|
|
pass
|
|
|
|
@property
|
|
def storage(self):
|
|
return getattr(self, '_storage', None) or self.field.storage or self.source_file.storage
|
|
|
|
@storage.setter
|
|
def storage(self, storage):
|
|
self._storage = storage
|
|
|
|
def __getstate__(self):
|
|
return dict(
|
|
attname=self.attname,
|
|
instance=self.instance,
|
|
)
|
|
|
|
def __setstate__(self, state):
|
|
self.attname = state['attname']
|
|
self.instance = state['instance']
|
|
self.field = getattr(self.instance.__class__, self.attname)
|
|
|
|
|
|
class ProcessedImageFieldFile(ImageFieldFile):
|
|
def save(self, name, content, save=True):
|
|
new_filename = self.field.spec.generate_filename(self.instance, name)
|
|
img, content = self.field.spec.process_content(content,
|
|
new_filename, self)
|
|
return super(ProcessedImageFieldFile, self).save(name, content, save)
|