Django

Code

Ticket #4115: contrib.thumbnails.patch

File contrib.thumbnails.patch, 27.3 kB (added by SmileyChris, 1 year ago)

First cut... no tests but read the documentation for the low-down

  • django/contrib/thumbnails/base.py

    old new  
     1from django.conf import settings 
     2import os 
     3from StringIO import StringIO 
     4from PIL import Image 
     5from exceptions import ThumbnailNoData, ThumbnailInvalidImage 
     6from methods import scale 
     7 
     8__all__ = ('Thumbnail',) 
     9 
     10class Thumbnail(object): 
     11    method = scale 
     12    base_url = settings.MEDIA_URL 
     13    root = settings.MEDIA_ROOT 
     14 
     15    def __init__(self, filename='', data=None, overwrite=False, size=None): 
     16        self._data = data 
     17        if size: 
     18            self.size = size 
     19        self.filename = filename 
     20        self.overwrite = overwrite 
     21        if data: 
     22            # If data was given and the thumbnail does not already exist, 
     23            # generate thumbnail image now. 
     24            self.make_thumbnail(data) 
     25 
     26    def get_filename(self): 
     27        return self._filename 
     28    def set_filename(self, filename): 
     29        if filename: 
     30            filename = filename % {'x': self.size[0], 'y': self.size[1], 'method': self.method.__name__} 
     31            filename = os.path.normpath(filename).lstrip(os.sep) 
     32            if os.path.splitext(filename)[1] != '.jpg': 
     33                filename.append('.jpg') 
     34            filename = os.path.join(self.root, filename) 
     35        self._filename = filename 
     36    filename = property(get_filename, set_filename) 
     37 
     38    def get_thumbnail(self): 
     39        if hasattr(self, '_thumbnail'): 
     40            return self._thumbnail 
     41        try: 
     42            img = Image.open(self.filename) 
     43        except IOError, msg: 
     44            raise ThumbnailInvalidImage(msg) 
     45        self._thumbnail = img 
     46        return img 
     47    thumbnail = property(get_thumbnail) 
     48 
     49    def make_thumbnail(self, data): 
     50        if self.overwrite or not os.path.isfile(self.filename): 
     51            try: 
     52                original = Image.open(StringIO(data)) 
     53            except IOError, msg: 
     54                raise ThumbnailInvalidImage(msg) 
     55            self._original_image = original 
     56            thumbnail = self.method() 
     57            self._thumbnail = thumbnail 
     58            if self.filename: 
     59                thumbnail.save(self.filename, "JPEG") 
     60 
     61    def get_url(self): 
     62        if hasattr(self, '_url'): 
     63            return self._url 
     64        filename = self.filename 
     65        if not os.path.isfile(filename): 
     66            raise ThumbnailNoData 
     67        url = os.path.normpath(filename[len(self.root):]).lstrip(os.sep) 
     68        url = os.path.join(self.base_url, url) 
     69        if os.sep != '/': 
     70            url = url.replace(os.sep, '/') 
     71        self._url = url 
     72        return url 
     73    url = property(get_url) 
     74 
     75    # Make the object will output it's url to Django templates. 
     76    __str__ = get_url 
     77 
     78    def get_original_image(self): 
     79        if hasattr(self, '_original_image'): 
     80            return self._original_image 
     81        raise ThumbnailNoData 
     82    original_image = property(get_original_image) 
     83 
     84    def delete(self): 
     85        if os.path.isfile(self.filename): 
     86            os.remove(self.filename) 
     87        self.filename = '' 
  • django/contrib/thumbnails/__init__.py

    old new  
     1from base import * 
     2from exceptions import * 
     3from methods import * 
  • django/contrib/thumbnails/exceptions.py

    old new  
     1class ThumbnailException(Exception): 
     2    pass 
     3 
     4class ThumbnailNoData(ThumbnailException): 
     5    pass 
     6 
     7class ThumbnailTooSmall(ThumbnailException): 
     8    pass 
     9 
     10class ThumbnailInvalidImage(ThumbnailException): 
     11    pass 
  • django/contrib/thumbnails/methods.py

    old new  
     1from PIL import Image 
     2from exceptions import ThumbnailTooSmall 
     3 
     4 
     5def scale(thumbnail): 
     6    """ Normal PIL thumbnail """ 
     7    img = thumbnail.original_image 
     8    size = thumbnail.size 
     9    if img.size[0] < size[0] and img.size[1] < size[1]: 
     10        raise ThumbnailTooSmall('Image should be at least %s wide or %s high' % size) 
     11    img.thumbnail(size, Image.ANTIALIAS) 
     12    return img 
     13 
     14 
     15def crop(thumbnail): 
     16    """ Crop the image down to the same ratio as `size` """ 
     17    img = thumbnail.original_image 
     18    size = thumbnail.size 
     19 
     20    if img.size[0] < size[0] or img.size[1] < size[1]: 
     21        raise ThumbnailTooSmall('Image must be at least %s wide and %s high' % size) 
     22 
     23    image_x, image_y = img.size 
     24 
     25    crop_ratio = size[0] / float(size[1]) 
     26    image_ratio = image_x / float(image_y) 
     27 
     28    if crop_ratio < image_ratio: 
     29        # x needs to shrink 
     30        top = 0 
     31        bottom = image_y 
     32        crop_width = int(image_y * crop_ratio) 
     33        left = (image_x - crop_width) // 2 
     34        right = left + crop_width 
     35    else: 
     36        # y needs to shrink 
     37        left = 0 
     38        right = image_x 
     39        crop_height = int(image_x * crop_ratio) 
     40        top = (image_y - crop_height) // 2 
     41        bottom = top + crop_height 
     42 
     43    img = img.crop((left, top, right, bottom)) 
     44    return img.resize(size, Image.ANTIALIAS) 
     45 
     46 
     47def squash(thumbnail): 
     48    """ Resize the image down to exactly `size` (changes ratio) """ 
     49    img = thumbnail.original_image 
     50    size = thumbnail.size 
     51    if img.size[0] < size[0] or img.size[1] < size[1]: 
     52        raise ThumbnailTooSmall('Image must be at least %s wide and %s high' % size) 
     53    return img.resize(size, Image.ANTIALIAS) 
  • django/contrib/thumbnails/__init__.py

    old new  
     1from base import * 
     2from exceptions import * 
     3from methods import * 
  • django/contrib/thumbnails/base.py

    old new  
     1from django.conf import settings 
     2import os 
     3from StringIO import StringIO 
     4from PIL import Image 
     5from exceptions import ThumbnailNoData, ThumbnailInvalidImage 
     6from methods import scale 
     7 
     8__all__ = ('Thumbnail',) 
     9 
     10class Thumbnail(object): 
     11    method = scale 
     12    base_url = settings.MEDIA_URL 
     13    root = settings.MEDIA_ROOT 
     14 
     15    def __init__(self, filename='', data=None, overwrite=False, size=None): 
     16        self._data = data 
     17        if size: 
     18            self.size = size 
     19        self.filename = filename 
     20        self.overwrite = overwrite 
     21        if data: 
     22            # If data was given and the thumbnail does not already exist, 
     23            # generate thumbnail image now. 
     24            self.make_thumbnail(data) 
     25 
     26    def get_filename(self): 
     27        return self._filename 
     28    def set_filename(self, filename): 
     29        if filename: 
     30            filename = filename % {'x': self.size[0], 'y': self.size[1], 'method': self.method.__name__} 
     31            filename = os.path.normpath(filename).lstrip(os.sep) 
     32            if os.path.splitext(filename)[1] != '.jpg': 
     33                filename.append('.jpg') 
     34            filename = os.path.join(self.root, filename) 
     35        self._filename = filename 
     36    filename = property(get_filename, set_filename) 
     37 
     38    def get_thumbnail(self): 
     39        if hasattr(self, '_thumbnail'): 
     40            return self._thumbnail 
     41        try: 
     42            img = Image.open(self.filename) 
     43        except IOError, msg: 
     44            raise ThumbnailInvalidImage(msg) 
     45        self._thumbnail = img 
     46        return img 
     47    thumbnail = property(get_thumbnail) 
     48 
     49    def make_thumbnail(self, data): 
     50        if self.overwrite or not os.path.isfile(self.filename): 
     51            try: 
     52                original = Image.open(StringIO(data)) 
     53            except IOError, msg: 
     54                raise ThumbnailInvalidImage(msg) 
     55            self._original_image = original 
     56            thumbnail = self.method() 
     57            self._thumbnail = thumbnail 
     58            if self.filename: 
     59                thumbnail.save(self.filename, "JPEG") 
     60 
     61    def get_url(self): 
     62        if hasattr(self, '_url'): 
     63            return self._url 
     64        filename = self.filename 
     65        if not os.path.isfile(filename): 
     66            raise ThumbnailNoData 
     67        url = os.path.normpath(filename[len(self.root):]).lstrip(os.sep) 
     68        url = os.path.join(self.base_url, url) 
     69        if os.sep != '/': 
     70            url = url.replace(os.sep, '/') 
     71        self._url = url 
     72        return url 
     73    url = property(get_url) 
     74 
     75    # Make the object will output it's url to Django templates. 
     76    __str__ = get_url 
     77 
     78    def get_original_image(self): 
     79        if hasattr(self, '_original_image'): 
     80            return self._original_image 
     81        raise ThumbnailNoData 
     82    original_image = property(get_original_image) 
     83 
     84    def delete(self): 
     85        if os.path.isfile(self.filename): 
     86            os.remove(self.filename) 
     87        self.filename = '' 
  • django/contrib/thumbnails/exceptions.py

    old new  
     1class ThumbnailException(Exception): 
     2    pass 
     3 
     4class ThumbnailNoData(ThumbnailException): 
     5    pass 
     6 
     7class ThumbnailTooSmall(ThumbnailException): 
     8    pass 
     9 
     10class ThumbnailInvalidImage(ThumbnailException): 
     11    pass 
  • django/contrib/thumbnails/methods.py

    old new  
     1from PIL import Image 
     2from exceptions import ThumbnailTooSmall 
     3 
     4 
     5def scale(thumbnail): 
     6    """ Normal PIL thumbnail """ 
     7    img = thumbnail.original_image 
     8    size = thumbnail.size 
     9    if img.size[0] < size[0] and img.size[1] < size[1]: 
     10        raise ThumbnailTooSmall('Image should be at least %s wide or %s high' % size) 
     11    img.thumbnail(size, Image.ANTIALIAS) 
     12    return img 
     13 
     14 
     15def crop(thumbnail): 
     16    """ Crop the image down to the same ratio as `size` """ 
     17    img = thumbnail.original_image 
     18    size = thumbnail.size 
     19 
     20    if img.size[0] < size[0] or img.size[1] < size[1]: 
     21        raise ThumbnailTooSmall('Image must be at least %s wide and %s high' % size) 
     22 
     23    image_x, image_y = img.size 
     24 
     25    crop_ratio = size[0] / float(size[1]) 
     26    image_ratio = image_x / float(image_y) 
     27 
     28    if crop_ratio < image_ratio: 
     29        # x needs to shrink 
     30        top = 0 
     31        bottom = image_y 
     32        crop_width = int(image_y * crop_ratio) 
     33        left = (image_x - crop_width) // 2 
     34        right = left + crop_width 
     35    else: 
     36        # y needs to shrink 
     37        left = 0 
     38        right = image_x 
     39        crop_height = int(image_x * crop_ratio) 
     40        top = (image_y - crop_height) // 2 
     41        bottom = top + crop_height 
     42 
     43    img = img.crop((left, top, right, bottom)) 
     44    return img.resize(size, Image.ANTIALIAS) 
     45 
     46 
     47def squash(thumbnail): 
     48    """ Resize the image down to exactly `size` (changes ratio) """ 
     49    img = thumbnail.original_image 
     50    size = thumbnail.size 
     51    if img.size[0] < size[0] or img.size[1] < size[1]: 
     52        raise ThumbnailTooSmall('Image must be at least %s wide and %s high' % size) 
     53    return img.resize(size, Image.ANTIALIAS) 
  • django/contrib/thumbnails/templatetags/thumbnails.py

    old new  
     1from django.template import Library 
     2from django.contrib.thumbnails import Thumbnail, crop, squash, ThumbnailException 
     3from django.conf import settings 
     4import os.path 
     5 
     6register = Library() 
     7 
     8class ThumbnailCrop(Thumbnail): 
     9    method = crop 
     10 
     11class ThumbnailSquash(Thumbnail): 
     12    method = squash 
     13 
     14 
     15#@register.filter 
     16def thumbnail(file, size): 
     17    return create_thumbnail(Thumbnail, file, size) 
     18register.filter(thumbnail) 
     19 
     20 
     21#@register.filter 
     22def thumbnail_crop(file, size): 
     23    return create_thumbnail(ThumbnailCrop, file, size) 
     24register.filter(thumbnail_crop) 
     25 
     26 
     27#@register.filter 
     28def thumbnail_squash(file, size): 
     29    return create_thumbnail(ThumbnailSquash, file, size) 
     30register.filter(thumbnail_squash) 
     31 
     32 
     33def create_thumbnail(thumbnail_cls, file, size_string): 
     34    """ 
     35    Creates a thumbnail image for the file (which must exist on MEDIA_ROOT) 
     36    and returns a url to this image. 
     37     
     38    If the thumbnail image is not found, an empty string will be returned. 
     39    """ 
     40    # Define the size. 
     41    size = [int(x) for x in size_string.split('x')] 
     42     
     43    # Define the filename, then create the thumbnail object. 
     44    basename, ext = os.path.splitext(file) 
     45    thumbnail_filename = '%s_%s_%%(method)s%s' % (basename, size_string, ext) 
     46    original_filename = os.path.join(settings.MEDIA_ROOT, file) 
     47     
     48    # See if the thumbnail exists already (and is newer than the 
     49    # original filename). 
     50    try: 
     51        thumbnail = thumbnail_cls(thumbnail_filename, size=size) 
     52        if os.path.getmtime(original_filename) > os.path.getmtime(thumbnail.filename): 
     53            thumbnail.delete() 
     54        else: 
     55            return thumbnail.url 
     56    except (ThumbnailException, OSError): 
     57        # Couldn't get the thumbnail (or something else went wrong). 
     58        pass 
     59 
     60    # Read the original file from disk. 
     61    try: 
     62        data = open(original_filename, 'rb').read() 
     63    except OSError: 
     64        # Couldn't read the original file. 
     65        return '' 
     66     
     67    # Generate the thumbnail. 
     68    try: 
     69        thumbnail = thumbnail_cls(thumbnail_filename, data, size=size) 
     70    except ThumbnailException: 
     71        return '' 
     72 
     73    return thumbnail 
  • django/contrib/thumbnails/templatetags/thumbnails.py

    old new  
     1from django.template import Library 
     2from django.contrib.thumbnails import Thumbnail, crop, squash, ThumbnailException 
     3from django.conf import settings 
     4import os.path 
     5 
     6register = Library() 
     7 
     8class ThumbnailCrop(Thumbnail): 
     9    method = crop 
     10 
     11class ThumbnailSquash(Thumbnail): 
     12    method = squash 
     13 
     14 
     15#@register.filter 
     16def thumbnail(file, size): 
     17    return create_thumbnail(Thumbnail, file, size) 
     18register.filter(thumbnail) 
     19 
     20 
     21#@register.filter 
     22def thumbnail_crop(file, size): 
     23    return create_thumbnail(ThumbnailCrop, file, size) 
     24register.filter(thumbnail_crop) 
     25 
     26 
     27#@register.filter 
     28def thumbnail_squash(file, size): 
     29    return create_thumbnail(ThumbnailSquash, file, size) 
     30register.filter(thumbnail_squash) 
     31 
     32 
     33def create_thumbnail(thumbnail_cls, file, size_string): 
     34    """ 
     35    Creates a thumbnail image for the file (which must exist on MEDIA_ROOT) 
     36    and returns a url to this image. 
     37     
     38    If the thumbnail image is not found, an empty string will be returned. 
     39    """ 
     40    # Define the size. 
     41    size = [int(x) for x in size_string.split('x')] 
     42     
     43    # Define the filename, then create the thumbnail object. 
     44    basename, ext = os.path.splitext(file) 
     45    thumbnail_filename = '%s_%s_%%(method)s%s' % (basename, size_string, ext) 
     46    original_filename = os.path.join(settings.MEDIA_ROOT, file) 
     47     
     48    # See if the thumbnail exists already (and is newer than the 
     49    # original filename). 
     50    try: 
     51        thumbnail = thumbnail_cls(thumbnail_filename, size=size) 
     52        if os.path.getmtime(original_filename) > os.path.getmtime(thumbnail.filename): 
     53            thumbnail.delete() 
     54        else: 
     55            return thumbnail.url 
     56    except (ThumbnailException, OSError): 
     57        # Couldn't get the thumbnail (or something else went wrong). 
     58        pass 
     59 
     60    # Read the original file from disk. 
     61    try: 
     62        data = open(original_filename, 'rb').read() 
     63    except OSError: 
     64        # Couldn't read the original file. 
     65        return '' 
     66     
     67    # Generate the thumbnail. 
     68    try: 
     69        thumbnail = thumbnail_cls(thumbnail_filename, data, size=size) 
     70    except ThumbnailException: 
     71        return '' 
     72 
     73    return thumbnail 
  • docs/thumbnails.txt

    old new  
     1========================= 
     2django.contrib.thumbnails 
     3========================= 
     4 
     5The ``django.contrib.thumbnails`` package, part of the `"django.contrib" add-ons`_, 
     6provides a way of thumbnailing images. 
     7 
     8It requires the Python Imaging Library (PIL_). 
     9 
     10.. _"django.contrib" add-ons: ../add_ons/ 
     11.. _PIL: http://www.pythonware.com/products/pil/ 
     12 
     13Template filters 
     14================ 
     15 
     16To use these template filters, add ``'django.contrib.thumbnails'`` to your 
     17``INSTALLED_APPS`` setting. Once you've done that, use 
     18``{% load thumbnails %}`` in a template to give your template access to the 
     19filters. 
     20 
     21The filters, all very similar in behaviour, are: 
     22 
     23 * ``thumbnail`` 
     24 * ``thumbnail_crop`` 
     25 * ``thumbnail_squash`` 
     26 
     27The only difference between them is the `Thumbnail methods`_ that they use. 
     28 
     29Using the thumbnail filters 
     30--------------------------- 
     31 
     32Usage:: 
     33 
     34    <img src="{{ object.imagefield|thumbnail:"150x100" }}" /> 
     35 
     36The filter is applied to a image field (not the url get from  
     37``get_[field]_url`` method of the model). Supposing the imagefield filename is 
     38``'image.jpg'``, it creates a thumbnailed image file proportionally resized 
     39down to a maximum of 150 pixels wide and 100 pixels high called 
     40``'image_150x100_scale.jpg'`` in the same location as the original image 
     41and returns the URL to this thumbnail image. 
     42 
     43The ``thumbnail_crop`` works exactly the same way but uses the crop method 
     44(and the filename would be called ``'image_150x100_crop.jpg'``). Similarly, 
     45``thumbnail_squash`` resizes the image to exactly the dimensions given 
     46(``'image_150x100_squash.jpg'``). 
     47 
     48If the thumbnail filename already exists, it is only overwritten if the date 
     49of the the original image file is newer than the thumbnail file. 
     50 
     51Rather than just outputting the url, you can reference any other properties 
     52(see the ```Thumbnail`` object properties`_ section below for a complete 
     53list):: 
     54 
     55    {% with object.imagefield|thumbnail:"150x100" as thumb %} 
     56    <img src="{{ thumb.url }}" width="{{ thumb.thumbnail.size.0 }}" height="{{ thumb.size.1 }}" /> 
     57    {% endwith %} 
     58 
     59 
     60Creating a thumbnail 
     61==================== 
     62 
     63The rest of this documentation deals with lower-level usage of thumbnails. 
     64 
     65To create a thumbnail object, simply call the ``Thumbnail`` class:: 
     66 
     67    >>> from django.contrib.thumbnails import * 
     68    >>> thumbnail = Thumbnail(filename, data, size=(100, 100)) 
     69 
     70The thumbnail object takes the following arguments: 
     71 
     72    =============== =========================================================== 
     73     Argument        Description 
     74    =============== =========================================================== 
     75 
     76    ``filename``    A string containing the path and filename to use when 
     77                    saving or retreiving this thumbnail image from disk 
     78                    (relative to the ``Thumbnail`` object's ``root`` property 
     79                    which defaults to ``settings.MEDIA_ROOT``). 
     80 
     81                    For advanced usage, see the ```Thumbnail```_ property  
     82                    section. 
     83 
     84    ``data``        A string or stream of the original image object to be 
     85                    thumbnailed. If not provided and a file matching the 
     86                    thumbnail can not be found, ``TemplateNoData`` will be 
     87                    raised. 
     88 
     89                    Example:: 
     90 
     91                        >>> Thumbnail('%(method)/s%(x)sx%(y)s/test.jpg', size=(60, 40)).filename 
     92                        '.../scale/60x40/test.jpg' 
     93 
     94    ``overwrite``   Set to ``True`` to overwrite the thumbnail with ``data`` 
     95                    even if an existing cached thumbnail is found. Defaults to 
     96                    ``False``. 
     97 
     98    ``size``        The size for the thumbnail image. Required unless using a 
     99                    subclass which provides a default ``size`` (see the 
     100                    `Custom thumbnails`_ section below). 
     101 
     102``Thumbnail`` object properties 
     103=============================== 
     104 
     105The thumbnail object which is created provides the following properties and 
     106functions: 
     107 
     108``filename`` 
     109------------ 
     110 
     111Reading this property returns the full path and filename to this thumbnail 
     112image. 
     113 
     114When you set this property, the filename string you provide is internally 
     115appended to the ``Thumbnail`` object's ``root`` property. 
     116 
     117You can use string formatting to generate the filename based on the 
     118thumbnailing method and size: 
     119 
     120  * ``%(x)s`` for the thumbnail target width, 
     121  * ``%(y)s`` for the thumbnail target height, 
     122  * ``%(method)s`` for the thumbnailing method. 
     123 
     124For example:: 
     125 
     126    >>> Thumbnail('%(media)/s%(x)sx%(y)s/test.jpg', size=(60, 40)).filename 
     127    '.../scale/60x40/test.jpg' 
     128 
     129Note: thumbnailed images are always saved as JPEG images, so if the filename 
     130string does not end in `'.jpg'`, this will be automatically appended to the 
     131thumbnail's filename. 
     132 
     133``original_image`` 
     134------------------ 
     135 
     136This read-only property returns a PIL ``Image`` containing the original 
     137image (passed in with ``data``). 
     138 
     139``thumbnail`` 
     140------------- 
     141 
     142This read-only property returns a PIL ``Image`` containing the thumbnail 
     143image. 
     144 
     145``url`` 
     146------- 
     147 
     148This read-only property returns the full url this thumbnail image. 
     149 
     150It is generated by appending the parsed ``filename`` string to the  
     151``Template`` object's ``base_url`` property. 
     152 
     153``delete()`` 
     154------------ 
     155 
     156Call this function to delete the thumbnail file if it exists on the disk. 
     157 
     158Custom thumbnails 
     159================= 
     160 
     161Similar to newforms, you can create a subclass to override the default 
     162properties of the ``Thumbnail`` base class:: 
     163 
     164    from django.contrib.thumbnails import Thumbnail 
     165 
     166    class MyThumbnail(Thumbnail): 
     167        size = (100, 100) 
     168 
     169Here are the properties you can provide to your subclass: 
     170 
     171    =============== =========================================================== 
     172     Property        Description 
     173    =============== =========================================================== 
     174 
     175    ``size``        Default size for creating thumbnails (no default). 
     176    ``base_url``    Base url for thumbnails (default is ``settings.MEDIA_URL``). 
     177    ``root``        Base directory for thumbnails (default is 
     178                    ``settings.MEDIA_ROOT``). 
     179    ``method``      The thumbnailing funciton to use (default is ``scale``). 
     180                    See the `Thumbnail methods`_ section below. 
     181 
     182Thumbnail methods 
     183================= 
     184 
     185There are two thumbnailing methods available in 
     186``django.contrib.thumbnails.methods`` 
     187 
     188``crop()`` 
     189---------- 
     190 
     191This method crops the image height or width to match the ratio of the thumbnail 
     192``size`` and then resizes it down to exactly the dimensions of ``size``. 
     193 
     194It requires the original image to be both as wide and as high as ``size``. 
     195 
     196``scale()`` 
     197----------- 
     198 
     199This is the normal PIL scaling method of proportionally resizing the image down 
     200to no greater than the thumbnail ``size`` dimensions. 
     201 
     202It requires the original image to be either as wide or as high as ``size``. 
     203 
     204``squash()`` 
     205------------ 
     206 
     207This method resizes the image down to exactly the dimensions given. This will 
     208potentially squash or stretch the image. 
     209 
     210It requires the original image to be both as wide and as high as ``size``. 
     211 
     212Making your own methods 
     213----------------------- 
     214 
     215To make your own thumbnailing function, create a function which accepts one 
     216parameter (``thumbnail``) and returns a PIL ``Image``. 
     217 
     218The ``thumbnail`` parameter will be a ``Thumbnail`` object, so you can use it 
     219to get the original image (it will raise ``ThumbnailNoData`` if no data was 
     220provided) and the thumbnail size:: 
     221 
     222    img = thumbnail.original_image 
     223    size = thumbnail.size 
     224 
     225Exceptions 
     226========== 
     227 
     228The following exceptions (all found in ``django.contrib.thumbnails.exceptions`` 
     229and all subclasses of ``ThumbnailException``) could be raised when using the 
     230``Thumbnail`` object: 
     231 
     232    =========================  ================================================ 
     233     Exception                  Reason 
     234    =========================  ================================================ 
     235 
     236    ``ThumbnailNoData``        Tried to get the ``original_image`` when no 
     237                               ``data`` was provided or tried to get the 
     238                               ``url`` when the file did not exist and no 
     239                               ``data`` was provided. 
     240    ``ThumbnailTooSmall``      The ``original_image`` was too small to 
     241                               thumbnail using the given thumbnailing method. 
     242    ``ThumbnailInvalidImage``  The ``data`` provided could not be decoded to 
     243                               a valid image format (or more rarely, using 
     244                               ``thumbnail`` to retreive an existing thumbnail 
     245                               file from disk which could not be decoded to a 
     246                               valid image format). 
     247 
     248Putting it all together 
     249======================= 
     250 
     251Here is a snippet of an example view which receives an image file from the user 
     252and saves a thumbnail of this image to a file named ``[userid].jpg``:: 
     253 
     254    from django.contrib.thumbnails import Thumbnail, crop, ThumbnailException 
     255 
     256    class ProfileThumbnail(Thumbnail): 
     257        size = (100, 100) 
     258        method = crop 
     259 
     260    def profile_image(request, id): 
     261        profile = get_object_or_404(Profile, pk=id) 
     262        if request.method == 'POST': 
     263            image = request.FILES.get('profile_image') 
     264            profile.has_image = False 
     265            if image: 
     266                filename = str(profile.id) 
     267                try: 
     268                    thumbnail = ProfileThumbnail(filename, image['content']) 
     269                    profile.has_image = True 
     270                except ThumbnailException: 
     271                    pass 
     272            profile.save() 
     273            return HttpResponseRedirect('../') 
     274        ...