Hello,
(This is my first time contributing to a forum -- so just let me know if I'm doing this wrong! Sorry about the duplicate post, the editor got a little buggy on my the first found and I accidentally posted the message before it was complete.)
I have the following use-cases:
- Admins would like to upload an image, and choose how the image gets cropped for each of the image variants.
- Admins would like to upload an image, and choose how a watermark is positioned / scaled on the image.
What I would love is to be able to use a special kind of spec field and processor which receives a reference to the model instance itself -- not just the image -- so it could combine values from other model fields.
Let me walk you through an example I've been working on: An image with a custom crop.
#models.py
image = models.ImageField(blank=True, null=True)
square_150_crop_properties = { 'source':'image', 'crop_field':'square_150_crop', 'resize_method':'fill', 'width':150, 'height':150, 'upscale':False }
square_150_crop = ImageCropField(null=True, blank=True, properties=square_150_crop_properties)
square_150 = InstanceSpecField( source='image', instance_processors=[PositionCrop(square_150_crop_properties)], hash_key_values=['square_150_crop'])
We're using a custom processor to which we pass custom settings. The processor function has been modified to receive both the image value *and* a reference to the model instance itself:
#processors.py
class PositionCrop(object):
def __init__(self, options):
self.options = options
self.crop_position_field = options['crop_field']
self.resize_method = options['resize_method']
self.width = options['width']
self.height = options['height']
self.upscale = options['upscale'] or False
def process(self, image, instance):
#Step 1, crop based on crop position
crop_value = getattr(instance, self.crop_position_field)
original_width = image.size[0]
original_height = image.size[1]
In addition, it will need a special hashing/picking function since we now trigger a change to the variant not just based on the image value, but the crop value in this case.
#InstanceSpecField
def get_hash(self):
keys = [
self.source.name,
self.field.processors,
self.field.instance_processors,
self.field.format,
self.field.options,
self.autoconvert,
]
instance = self.instance
#Use the actual values of the fields to hash the instance
#REQUIRES INSTANCE:
for extra_field in self.field.extra_hash_key_values:
field = getattr(self.instance, extra_field)
field_hash = "%s_%s"%(extra_field, field)
keys.append(field_hash)
return hashers.pickle(keys)
My questions are:
1) Is there a good solution that already exists that would accomplish the use cases above?
2) If not, does this approach seem good and that it would be helpful to others?
3) If this seems like a good solution, what are the steps I should take to get this integrated into the core?