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?
- 6,454
- 5
- 44
- 50
- 1,725
- 2
- 15
- 27
-
Maybe this solution could work in your case, as well: http://stackoverflow.com/a/38718010/621690 – Risadinha May 17 '17 at 12:48
6 Answers
I managed to do it after a lot of digging. Unfortunately I couldn't find the source I used (too many tabs, too many didn't work..) . So the idea was to create an Image Widget, that appends some html script.
from django.contrib.admin.widgets import AdminFileWidget
class AdminImageWidget(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" width="150" height="150" style="object-fit: cover;"/></a> %s ' % \
(image_url, image_url, file_name, _('')))
output.append(super(AdminFileWidget, self).render(name, value, attrs))
return mark_safe(u''.join(output))
class CollectionImageInline(admin.TabularInline):
formfield_overrides = {models.ImageField: {'widget': AdminImageWidget}}
the result : (I changed admin theme to default regardless to this issue)
-
2This worked, thanks. I would add imports on top: `from django.utils.safestring import marksafe from django.db import models` – horbor Nov 16 '17 at 13:39
You'll want to add a method to the model.py:
def thumbnail(self):
return u'<img src="%s" />' % (self.image.url)
thumbnail.short_description = 'Thumbnail'
Then in admin.py you'll want to add:
fields = ( 'thumbnail', )
readonly_fields = ('thumbail',)
That will add the thumbnail there.
- 242
- 2
- 11
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}
}
- 378
- 1
- 2
- 14
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',)
- 138
- 9
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
- 4,264
- 5
- 30
- 41
-
Thankyou for your answer. But when I click "submit" or "delete" the following error comes up ```'AdminImageWidget' object has no attribute 'decompress'``` – Mrcreamio Dec 14 '21 at 08:11
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:
- 6,454
- 5
- 44
- 50