time

Gorgeous thumbnails in Django admin

Short snippet how-to build thumb for some field and show in change list.

I'm going to use sorl-thumbnail.

pip install sorl-thumbnail

Image thumbnail for admin change list

Mixin

from sorl.thumbnail import get_thumbnail

class ThumbMixin:
    thumb_size = '100x100'
    thumb_crop = 'center'
    thumb_quality = 99
    thumb_field = 'image'
    thumb_keep_original = False

    def thumb(self):
        field = getattr(self, self.thumb_field, None)
        if field:
            if self.thumb_keep_original:
                return "<a href='{0}' target='_blank'><img src='{1}' alt='' /></a>".format(field.url, field.url)
            else:
                th = get_thumbnail(field, self.thumb_size, crop=self.thumb_crop, quality=self.thumb_quality)
                return "<a href='{0}' target='_blank'><img src='{1}' alt='' /></a>".format(field.url, th.url)
        else:
            return '-'
    thumb.allow_tags = True
    thumb.short_description = 'Thumb'

Test model

from django.db import models
from utils.mixins import ThumbMixin

class Book(ThumbMixin, models.Model):
    title = models.CharField(u'Title', max_length=255)
    photo = models.ImageField(u'Photo', upload_to=photo_upload_path)

    thumb_field = 'photo'
    thumb_size = '150x150'

    class Meta:
        verbose_name_plural = u'Books'
        verbose_name = u'book'

    def __unicode__(self):
        return self.title

Definition in admin.py

class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'thumb')
admin.site.register(Book, BookAdmin)

Image thumbnail for admin change form

To show image instead of the file path in edit pages, using ImageWidget is nice way to do it. First, define auxiliary file widget and ModelAdmin.

# file utils.py

from django.contrib.admin.widgets import AdminFileWidget
from django.utils.safestring import mark_safe
from django.contrib import admin

class ImageWidget(AdminFileWidget):
    def render(self, name, value, attrs=None):
        output = []
        if value and getattr(value, "url", None):
            image_url = value.url
            file_name = str(value)
            output.append(u' <a href="%s" target="_blank"><img src="%s" alt="%s" /></a>' % \
                          (image_url, image_url, file_name))
        output.append(super(AdminFileWidget, self).render(name, value, attrs))
        return mark_safe(u''.join(output))


class ImageWidgetAdmin(admin.ModelAdmin):
    image_fields = []

    def formfield_for_dbfield(self, db_field, **kwargs):
        if db_field.name in self.image_fields:
            request = kwargs.pop("request", None)
            kwargs['widget'] = ImageWidget
            return db_field.formfield(**kwargs)
        return super(ImageWidgetAdmin, self).formfield_for_dbfield(db_field, **kwargs)

Usage

# file admin.py
from .utils import ImageWidgetAdmin

class MovieAdmin(ImageWidgetAdmin):
    image_fields = ['poster']
comments powered by Disqus