- Author:
- fivethreeo
- Posted:
- August 14, 2008
- Language:
- Python
- Version:
- .96
- Score:
- 2 (after 2 ratings)
Usage:
from django.db import models
from imagevariations.fields import ImageVariationsField, Thumbnail
class Image(models.Model):
name = models.CharField(max_length=20)
image = ImageVariationsField(upload_to='testimages', variations=(Thumbnail,) )
How to use in templates:
Use the lowercase name of the image variation class.
{{ object.image.variations.thumbnail.url }}
By default all image variations will use the same storage backend as the field but can be replaced per variation by setting self.storage on the variation class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | from django.db.models.fields.files import ImageField, ImageFieldFile
from django.core.files.base import File, ContentFile
class ImageVariation(File):
variation_suffix = 'variation'
def __init__(self, instance):
self.field = instance.field
self.instance = instance.instance
self.storage = getattr(self, 'storage', instance.storage)
name = getattr(self.instance, self.field.name) or u''
self._name = self.get_variation_name(unicode(name))
self._closed = False
def get_variation_name(self, name):
try:
dot_index = name.rindex('.')
except:
name = '%s%s' % (name, self.variation_suffix)
else:
name = '%s%s%s' % (name[:dot_index], self.variation_suffix, name[dot_index:])
return name
def save(self, name, content):
self.storage.save(self.name, content)
def delete(self):
self.close()
self.storage.delete(self.name)
def _require_file(self):
if not self:
raise ValueError("The '%s' attribute has no file associated with it." % self.field.name)
def _get_file(self):
self._require_file()
if not hasattr(self, '_file'):
self._file = self.storage.open(self.name, 'rb')
return self._file
file = property(_get_file)
def _get_path(self):
self._require_file()
return self.storage.path(self.name)
path = property(_get_path)
def _get_url(self):
self._require_file()
return self.storage.url(self.name)
url = property(_get_url)
def open(self, mode='rb'):
self._require_file()
return super(ImageVariation, self).open(mode)
# open() doesn't alter the file's contents, but it does reset the pointer
open.alters_data = True
from StringIO import StringIO
def get_file(data):
if hasattr(data, 'temporary_file_path'):
file = data.temporary_file_path()
else:
if hasattr(data, 'read'):
file = StringIO(data.read())
else:
file = StringIO(data['content'])
return file
WIDTH, HEIGHT = 0, 1
def resize_image(content, size):
from PIL import Image
img = Image.open(get_file(content))
if img.size[0] > size['width'] or img.size[1] > size['height']:
if size['force']:
target_height = float(size['height'] * img.size[WIDTH]) / size['width']
if target_height < img.size[HEIGHT]: # Crop height
crop_side_size = int((img.size[HEIGHT] - target_height) / 2)
img = img.crop((0, crop_side_size, img.size[WIDTH], img.size[HEIGHT] - crop_side_size))
elif target_height > img.size[HEIGHT]: # Crop width
target_width = float(size['width'] * img.size[HEIGHT]) / size['height']
crop_side_size = int((img.size[WIDTH] - target_width) / 2)
img = img.crop((crop_side_size, 0, img.size[WIDTH] - crop_side_size, img.size[HEIGHT]))
img.thumbnail((size['width'], size['height']), Image.ANTIALIAS)
out = StringIO()
try:
img.save(out, optimize=1)
except IOError:
img.save(out)
return out
else:
return content
class Thumbnail(ImageVariation):
variation_suffix = 'thumbnail'
def save(self, name, content):
self.storage.save(self.name, resize_image(content, {'height': 200, 'width': 200, 'force': True} ) )
class ImageVariationsDescriptor(object):
def __get__(self, instance=None, owner=None):
self.variations = [ (v(instance))
for v in instance.field.variations ]
for v in self.variations:
setattr(self, v.__class__.__name__.lower(), v)
return self
def save(self, name, content):
for v in self.variations:
content.seek(0)
v.save(name, content)
def delete(self):
for v in self.variations:
v.delete()
class ImageVariationsFieldFile(ImageFieldFile):
variations = ImageVariationsDescriptor()
def save(self, name, content, save=True):
super(ImageVariationsFieldFile, self).save(name, content, save=save)
self.variations.save(name, content)
def delete(self, save=True):
self.variations.delete()
super(ImageVariationsFieldFile, self).delete(save)
class ImageVariationsField(ImageField):
attr_class = ImageVariationsFieldFile
def __init__(self, variations=[], *args, **kwargs):
self.variations = variations
super(ImageVariationsField, self).__init__(*args, **kwargs)
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
Please login first before commenting.