Remove ImageSpecFieldFile in favor of ImageSpecFile

This commit is contained in:
Eric Eldredge 2012-10-15 23:53:05 -04:00
parent 2a33a2ad88
commit c0b79a227d
4 changed files with 44 additions and 132 deletions

View file

@ -15,6 +15,9 @@ class ImageSpecFile(ImageFieldFile):
self.source_file = source_file
self.spec_id = spec_id
def get_hash(self):
return self.spec.get_hash(self.source_file)
@property
def url(self):
self.validate()
@ -37,14 +40,18 @@ class ImageSpecFile(ImageFieldFile):
@property
def name(self):
source_filename = self.source_file.name
filepath, basename = os.path.split(source_filename)
filename = os.path.splitext(basename)[0]
extension = suggest_extension(source_filename, self.spec.format)
new_name = '%s%s' % (filename, extension)
cache_filename = ['cache', 'iktt'] + self.spec_id.split(':') + \
[filepath, new_name]
return os.path.join(*cache_filename)
name = self.spec.generate_filename(self.source_file)
if name is not None:
return name
else:
source_filename = self.source_file.name
filepath, basename = os.path.split(source_filename)
filename = os.path.splitext(basename)[0]
extension = suggest_extension(source_filename, self.spec.format)
new_name = '%s%s' % (filename, extension)
cache_filename = ['cache', 'iktt'] + self.spec_id.split(':') + \
[filepath, new_name]
return os.path.join(*cache_filename)
def generate(self, save=True):
return self.spec.generate_file(self.name, self.source_file, save)

View file

@ -1,124 +1,4 @@
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)
from django.db.models.fields.files import ImageFieldFile
class ProcessedImageFieldFile(ImageFieldFile):

View file

@ -1,4 +1,5 @@
from .files import ImageSpecFieldFile
from ...files import ImageSpecFile
from django.db.models.fields.files import ImageField
class ImageSpecFileDescriptor(object):
@ -10,8 +11,26 @@ class ImageSpecFileDescriptor(object):
if instance is None:
return self.field
else:
img_spec_file = ImageSpecFieldFile(instance, self.field,
self.attname)
field_name = getattr(self.field, 'image_field', None)
if field_name:
source_file = getattr(instance, field_name)
else:
image_fields = [getattr(instance, f.attname) for f in \
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.' % \
(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.' % (instance.__class__.__name__,
self.attname))
else:
source_file = image_fields[0]
img_spec_file = ImageSpecFile(self.field.spec, source_file,
self.attname)
instance.__dict__[self.attname] = img_spec_file
return img_spec_file

View file

@ -440,6 +440,12 @@ class SpecWrapper(object):
self.autoconvert = getattr(spec, 'autoconvert', True)
self.storage = getattr(spec, 'storage', None)
self.image_cache_backend = getattr(spec, 'image_cache_backend', None)
# TODO: get_hash default return value.
self.get_hash = getattr(spec, 'get_hash', lambda f: None)
# TODO: generate_filename default return value.
self.generate_filename = getattr(spec, 'generate_filename', lambda f: None)
# TODO: generate_file default return value.
self.generate_file = getattr(spec, 'generate_file', lambda f: None)
if not self.image_cache_backend:
from .imagecache.backends import get_default_image_cache_backend