54

I'm trying to show thumbnail images in Django admin, but I can only see the path to the images, but not the rendered images. I don't know what I'm doing wrong.

Server media URL:

from django.conf import settings
(r'^public/(?P<path>.*)$', 'django.views.static.serve',{'document_root': settings.MEDIA_ROOT}),

Function model:

def image_img(self):
        if self.image:
            return u'<img src="%s" />' % self.image.url_125x125
        else:
            return '(Sin imagen)'
        image_img.short_description = 'Thumb'
        image_img.allow_tags = True

admin.py:

class ImagesAdmin(admin.ModelAdmin):

    list_display= ('image_img','product',) 

And the result:

<img src="http://127.0.0.1:8000/public/product_images/6a00d8341c630a53ef0120a556b3b4970c.125x125.jpg" />
Serjik
  • 10,543
  • 8
  • 61
  • 70
Asinox
  • 6,747
  • 14
  • 61
  • 89

6 Answers6

76

This is in the source for photologue (see models.py, slightly adapted to remove irrelevant stuff):

def admin_thumbnail(self):
    return u'<img src="%s" />' % (self.image.url)
admin_thumbnail.short_description = 'Thumbnail'
admin_thumbnail.allow_tags = True

The list_display bit looks identical too, and I know that works. The only thing that looks suspect to me is your indentation - the two lines beginning image_img at the end of your models.py code should be level with def image_img(self):, like this:

def image_img(self):
    if self.image:
        return u'<img src="%s" />' % self.image.url_125x125
    else:
        return '(Sin imagen)'
image_img.short_description = 'Thumb'
image_img.allow_tags = True
Dominic Rodger
  • 97,747
  • 36
  • 197
  • 212
  • 1
    Where you put that image_img function ? I have written it under `class ImagesAdmin(admin.ModelAdmin):` but it gives me error as `Caught TypeError while rendering: image_img() takes exactly 1 argument (2 given)` – brsbilgic Sep 30 '11 at 00:08
  • @brsbilgic - It needs to go under your model, unless you add a second parameter after `self`, called something like `obj`, which represents the model you're using. See https://docs.djangoproject.com/en/dev/ref/contrib/admin/#modeladmin-methods. – Dominic Rodger Oct 02 '11 at 19:08
  • What if I also want to display the thumbnail on the model's edit page? Only just for reference, so the person knows what image is the current one uploaded? – alfetopito Oct 10 '13 at 17:14
  • Got it http://stackoverflow.com/questions/16307307/django-admin-show-image-from-imagefield (in case someone else is also wondering) – alfetopito Oct 10 '13 at 17:18
12

Update v. 1.9

Note that in Django v.1.9

image_tag.allow_tags = True

is depricated and you should use format_html(), format_html_join(), or mark_safe() instead

So your model.py should look like this:

...
from django.utils.html import mark_safe

def image_img(self):
    if self.image:
        return mark_safe('<img src="%s" />' % self.image.url_125x125)
    else:
        return '(Sin imagen)'
    image_img.short_description = 'Thumb'

and in your admin.py add:

list_display= ('image_img','product',)
readonly_fields = ('image_img',)

and for adding it in the 'Edit mode' of your admin panel in your admin.py add:

fields = ( 'image_img', )
Henrique Andrade
  • 855
  • 1
  • 12
  • 25
palamunder
  • 2,555
  • 1
  • 19
  • 20
  • Notes: The `image_img()` method should accept an `instance`: `def image_img(self, instance):` and use`instance` instead of `self` for getting the URL. – Phil Gyford Dec 07 '16 at 14:04
  • `def image_img(self):`, then you can use `self.field_name` to get the field, don't need instance param (my Django version v1.9) @ Phil Gyford – Cloud Dec 21 '16 at 12:31
7

Add a method in your model (models.py):

def image_tag(self):
    return u'<img src="%s" />' % <URL to the image>
image_tag.short_description = 'Image'
image_tag.allow_tags = True

and in your ModelAdmin (admin.py) add:

readonly_fields = ('image_tag',)
ksadowski
  • 161
  • 9
Avinash Garg
  • 1,374
  • 14
  • 18
6

Adding on to @dominic, I wanted to use this in multiple models, so I created a function that I could call in each model, inputing the image to be displayed.

For instance in one app I have:

from django.contrib import admin

from .models import Frontpage
from ..admin import image_file


class FrontpageAdmin(admin.ModelAdmin):
    list_display = ('image_thumb', ...)

    image_thumb = image_file('obj.image()') 

admin.site.register(Frontpage, FrontpageAdmin)

with image a function of Frontpage that returns an image.

In another app I have:

from django.contrib import admin

from .models import Exhibition
from ..admin import image_file


class ExhibitionAdmin(admin.ModelAdmin):
    list_display = ('first_image_thumb', ...)

    first_image_thumb = image_file('obj.related_object.image',
                                   short_description='First Image')

admin.site.register(Exhibition, ExhibitionAdmin)

This allows me to specify the image object and the short_description while keeping the boilerplate in another file. The function is:

from sorl.thumbnail import get_thumbnail
from django.conf import settings


def image_file(image, short_description='Image'):
    def image_thumb(self, obj):
        image = eval(image_thumb.image)
        if image:
            thumb = get_thumbnail(image.file, settings.ADMIN_THUMBS_SIZE)
            return u'<img width="{}" height={} src="{}" />'.format(thumb.width, thumb.height, thumb.url)
        else:
            return "No Image"

    image_thumb.__dict__.update({'short_description': short_description,
                                 'allow_tags': True,
                                 'image': image})
    return image_thumb
saul.shanabrook
  • 3,068
  • 3
  • 31
  • 49
3

Since the allow_tags has been deprecated, you should use format_html function. The example code look like this:

models.py file:

class TestAdminModel(models.Model):

    img = models.URLField()

admin.py file:

from django.utils.html import format_html

class TestAdmin(admin.ModelAdmin):
    list_display = ["id", "img", "thumbnail"]

    def thumbnail(self, obj):
        return format_html('<img src="{}" style="width: 130px; \
                           height: 100px"/>'.format(obj.img))

    thumbnail.short_description = 'thumbnail'

admin.site.register(models.TestAdminModel, TestAdmin)

The result looks like this: enter image description here

You can see more details from django documentation.

ramwin
  • 5,803
  • 3
  • 27
  • 29
1

With django-imagekit you can add any image like this:

from imagekit.admin import AdminThumbnail

@register(Fancy)
class FancyAdmin(ModelAdmin):
    list_display = ['name', 'image_display']
    image_display = AdminThumbnail(image_field='image')
    image_display.short_description = 'Image'

    # set this to also show the image in the change view
    readonly_fields = ['image_display']
Risadinha
  • 16,058
  • 2
  • 88
  • 91