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