Display thumbnail in Django admin inline

Viewed 6053

i'm new to Django and trying to change how inline images are presented in the admin panel. Can I add a Preview tag above each 'Currently' to and show thumbnail?

enter image description here

6 Answers

Following on, to @shaniqwa answer, django(2.2.7) now requires renderer in render(),

class AdminImageWidget(AdminFileWidget):

    def render(self, name, value, attrs=None, renderer=None):
        output = []

        if value and getattr(value, "url", None):
            image_url = value.url
            file_name = str(value)

            output.append(
                f' <a href="{image_url}" target="_blank">'
                f'  <img src="{image_url}" alt="{file_name}" width="150" height="150" '
                f'style="object-fit: cover;"/> </a>')

        output.append(super(AdminFileWidget, self).render(name, value, attrs, renderer))
        return mark_safe(u''.join(output))


class ProductImagesAdmin(admin.TabularInline):
    model = ProductImages
    extra = 1
    formfield_overrides = {
        models.ImageField: {'widget': AdminImageWidget}
    }

The simple solution that works for me in Django 3.0:

In models.py add:

from django.utils.safestring import mark_safe

def image_preview(self):
    if self.image:
        return mark_safe('<img src="{0}" width="150" height="150" />'.format(self.image.url))
    else:
        return '(No image)'

in admin.py:

class ProductImagesAdmin(admin.TabularInline):
    model = ProductImages
    readonly_fields = ('image_preview',)

Cleaned up version of the first answer https://stackoverflow.com/a/44051507/2020723 - ready of Django >3, python 3.x:

class AdminImageWidget(AdminFileWidget):
    """Admin widget for showing clickable thumbnail of Image file fields"""

    def render(self, name, value, attrs=None, renderer=None):
        html = super().render(name, value, attrs, renderer)
        if value and getattr(value, 'url', None):
            html = format_html('<a href="{0}" target="_blank"><img src="{0}" alt="{1}" width="150" height="150" style="object-fit: contain;"/></a>', value.url, str(value)) + html
        return html

Mar, 2022 Update:

This code can display the images of an inline model and this code works without changing any code so just copying and pasting it is OK.

"admin.py":

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

class AdminImageWidget(AdminFileWidget):

    def render(self, name, value, attrs=None, renderer=None):
        output = []

        if value and getattr(value, "url", None):
            image_url = value.url
            file_name = str(value)

            output.append(
                f'<a href="{image_url}" target="_blank">'
                f'<img src="{image_url}" alt="{file_name}" width="150" height="150" '
                f'style="object-fit: cover;"/> </a>')

        output.append(super(AdminFileWidget, self).render(name, value, attrs, renderer))
        return mark_safe(u''.join(output))

Also, this code is needed for an inline model and again, this code works without changing any code so just copying and pasting it is OK:

formfield_overrides = {
    models.ImageField: {'widget': AdminImageWidget}
}

So, bringing all together, as shown below, I used the code above to display the product images of the inline model "ProductImage" under the model "Product".

"admin.py":

from django.db import models
from django.utils.safestring import mark_safe
from django.contrib.admin.widgets import AdminFileWidget
from .models import Product, ProductImage

class AdminImageWidget(AdminFileWidget):

    def render(self, name, value, attrs=None, renderer=None):
        output = []

        if value and getattr(value, "url", None):
            image_url = value.url
            file_name = str(value)

            output.append(
                f'<a href="{image_url}" target="_blank">'
                f'<img src="{image_url}" alt="{file_name}" width="150" height="150" '
                f'style="object-fit: cover;"/> </a>')

        output.append(super(AdminFileWidget, self).render(name, value, attrs, renderer))
        return mark_safe(u''.join(output))

class ProductImageInline(admin.TabularInline):
    model = ProductImage
    formfield_overrides = {
        models.ImageField: {'widget': AdminImageWidget}
    }

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    inlines = [ProductImageInline]

This is how it looks like:

enter image description here

Related