August 21, 2012

November 25, 2019

Django, reStructuredText and image thumbnails

I use reStructuredText at my blog. I have decided to write my own simple directive for generating image thumbnails and returning html tags. I'm using sorl.thumbnail for this.

import os
from docutils import nodes
from docutils.parsers.rst import directives, Directive
from sorl.thumbnail import get_thumbnail
from project.settings import MEDIA_ROOT, MEDIA_URL
class Thumb(Directive):
def align(argument):
"""Conversion function for the "align" option."""
return directives.choice(argument, ('left', 'center', 'right'))
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec = {
'alt': directives.unchanged,
'height': directives.length_or_unitless,
'width': directives.length_or_percentage_or_unitless,
'align': align
def run(self):
alt = self.options.get('alt')
img = self.arguments[0].strip()
# Default parameters
width = 500
height = ''
align = 'center'
if 'width' in self.options:
width = self.options['width']
if 'height' in self.options:
height = self.options['height']
if 'align' in self.options:
align = self.options['align']
# Get image path.
if any(x in img for x in ['http', 'www']):
# Received path like /media/test/1.jpg
img_path = os.path.join(MEDIA_ROOT, img.replace(MEDIA_URL, ''))
# Received url like
project_root = os.path.abspath(os.path.dirname(__file__))
img_path = os.path.realpath(project_root + img)
if width and height:
size = '{0}x{1}'.format(width, height)
elif not width and height:
size = 'x{0}'.format(height)
size = str(width)
img_thumb = get_thumbnail(img_path, size, upscale=False, quality=99)
html = u'<a href="{0}" title="{1}" class="align-{2}">' \
u'<img src="{3}" alt="{4}" /></a>'.format(
img, alt, align, img_thumb.url, alt
return [nodes.raw('', html, format='html')]
directives.register_directive('thumb', Thumb)

Now I can use this in RST code.

.. thumb:: /media/test/1.jpg
    :alt: Test

.. thumb::
    :alt: Test

.. thumb:: /media/test/1.jpg
    :alt: Test
    :width: 300
    :height: 300

.. thumb:: /media/test/1.jpg
    :alt: Test
    :height: 200
© 2020 Przemysław Kołodziejczyk