Basic group profile and web/logo/description fields of the Group model
[xnet] / xnet / utils / images / fields.py
diff --git a/xnet/utils/images/fields.py b/xnet/utils/images/fields.py
new file mode 100644 (file)
index 0000000..4ff7d35
--- /dev/null
@@ -0,0 +1,116 @@
+# -*- encoding: utf-8 -*-
+"""
+django-thumbs by Antonio MelĂ©
+Modified by Arthur Darcet to support on demand resizing
+"""
+from django.db.models import ImageField
+from django.db.models.fields.files import ImageFieldFile
+from PIL import Image
+from django.core.files.base import ContentFile
+import cStringIO, re
+
+
+def generate_thumb(img, thumb_size, format):
+    img.seek(0) # see http://code.djangoproject.com/ticket/8222 for details
+    image = Image.open(img)
+    if image.mode not in ('L', 'RGB'):
+        image = image.convert('RGB')
+    thumb_w, thumb_h = thumb_size
+    if thumb_w == thumb_h and False:
+        xsize, ysize = image.size
+        minsize = min(xsize,ysize)
+        xnewsize = (xsize-minsize)/2
+        ynewsize = (ysize-minsize)/2
+        image2 = image.crop((xnewsize, ynewsize, xsize-xnewsize, ysize-ynewsize))
+        image2.load()
+        image2.thumbnail(thumb_size, Image.ANTIALIAS)
+    else:
+        image2 = image
+        image2.thumbnail(thumb_size, Image.ANTIALIAS)
+    io = cStringIO.StringIO()
+    if format.upper()=='JPG':
+        format = 'JPEG'
+    image2.save(io, format)
+    return ContentFile(io.getvalue())
+
+
+class ImageWithThumbsFieldFile(ImageFieldFile):
+    @staticmethod
+    def _get_for_size(s, (w,h)):
+        split = s.rsplit('.',1)
+        return u'{}.{}x{}.{}'.format(split[0],w,h,split[1])
+
+    def __getattr__(self, attr):
+        s = attr.split('url_')
+        if len(s) != 2 or 'x' not in s[1]:
+            raise AttributeError
+        if not self.name:
+            raise AttributeError('The picture has no file associated with it.')
+        size = map(int, s[1].split('x',1))
+        name = ImageWithThumbsFieldFile._get_for_size(self.name, size)
+        url = ImageWithThumbsFieldFile._get_for_size(self.url, size)
+        if not self.storage.exists(name):
+            thumb_content = generate_thumb(self, size, name.rsplit('.',1)[1])
+            self.storage.save(name, thumb_content)
+        return url
+
+    def delete(self, save=True):
+        directory, name = self.name.rsplit('/', 1)
+        _, files = self.storage.listdir(directory)
+        reg = re.compile(r'{}.[0-9]+x[0-9]+.{}'.format(*name.rsplit('.',1)))
+        for f in files:
+            if reg.match(f):
+                self.storage.delete(u'{}/{}'.format(directory, f))
+        super(ImageWithThumbsFieldFile, self).delete(save)
+
+
+class ImageWithThumbsField(ImageField):
+    attr_class = ImageWithThumbsFieldFile
+    """
+    Usage example:
+    ==============
+    photo = ImageWithThumbsField(upload_to='images', sizes=((125,125),(300,200),)
+
+    To retrieve image URL, exactly the same way as with ImageField:
+        my_object.photo.url
+    To retrieve thumbnails URL's just add the size to it:
+        my_object.photo.url_125x125
+        my_object.photo.url_300x200
+
+    Note: The 'sizes' attribute is not required. If you don't provide it,
+    ImageWithThumbsField will act as a normal ImageField
+
+    How it works:
+    =============
+    For each size in the 'sizes' atribute of the field it generates a
+    thumbnail with that size and stores it following this format:
+
+    available_filename.[width]x[height].extension
+
+    Where 'available_filename' is the available filename returned by the storage
+    backend for saving the original file.
+
+    Following the usage example above: For storing a file called "photo.jpg" it saves:
+    photo.jpg          (original file)
+    photo.125x125.jpg  (first thumbnail)
+    photo.300x200.jpg  (second thumbnail)
+
+    With the default storage backend if photo.jpg already exists it will use these filenames:
+    photo_.jpg
+    photo_.125x125.jpg
+    photo_.300x200.jpg
+
+    Note: django-thumbs assumes that if filename "any_filename.jpg" is available
+    filenames with this format "any_filename.[widht]x[height].jpg" will be available, too.
+
+    To do:
+    ======
+    Add method to regenerate thubmnails
+
+    """
+    def __init__(self, verbose_name=None, name=None, width_field=None, height_field=None, **kwargs):
+        self.verbose_name=verbose_name
+        self.name=name
+        self.width_field=width_field
+        self.height_field=height_field
+        super(ImageField, self).__init__(**kwargs)