Django Admin Show Image from Imagefield

While I can show the loaded image in list_display, is it possible to do this on every page of the model (like on the page you get to change the model)?

Quick sample model:

Class Model1(models.Model): image = models.ImageField(upload_to=directory) 

The default admin shows the URL of the uploaded image, but not the image itself.

Thank!

+47
django django-admin
Apr 30 '13 at 19:13
source share
8 answers

Sure. In your model class add this method:

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

and in your admin.py add:

 fields = ( 'image_tag', ) readonly_fields = ('image_tag',) 

to your ModelAdmin . If you want to limit the ability to edit the image field, be sure to add it to the exclude attribute.

Note: with Django 1.8 and 'image_tag' only in readonly_fields it did not display. With 'image_tag' in fields only, it threw an unknown field error. You need this both in the fields and in readonly_fields for the correct display.

+102
Apr 30 '13 at 19:29
source share
โ€” -

In addition to Michael S. O'Connor's answer

Please note that in Django v.1.9

 image_tag.allow_tags = True 

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

Therefore, if you store your downloaded files in the public / directory folder, your code should look like this:

 Class Model1(models.Model): image = models.ImageField(upload_to=directory) def image_tag(self): return mark_safe('<img src="/directory/%s" width="150" height="150" />' % (self.image)) image_tag.short_description = 'Image' 

and in your admin.py add:

 fields = ['image_tag'] readonly_fields = ['image_tag'] 
+50
Jun 22 '16 at 10:16
source share

This can be done in admin without changing the model.

 from django.utils.html import format_html class Model1Admin(admin.ModelAdmin): def image_tag(self, obj): return format_html('<img src="{}" />'.format(obj.image.url)) image_tag.short_description = 'Image' list_display = ['image_tag',] admin.site.register(Model1, Model1Admin) 
+22
Nov 21 '16 at 8:31
source share

For Django 1.9 To show the image instead of the file path on the edit pages, using ImageWidget is a great way to do this.

 from django.contrib.admin.widgets import AdminFileWidget from django.utils.translation import ugettext as _ from django.utils.safestring import mark_safe from django.contrib import admin 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" /></a> %s ' % \ (image_url, image_url, file_name, _('Change:'))) 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'] = AdminImageWidget return db_field.formfield(**kwargs) return super(ImageWidgetAdmin, self).formfield_for_dbfield(db_field, **kwargs) 

Application:

 class IndividualBirdAdmin(ImageWidgetAdmin): image_fields = ['thumbNail', 'detailImage'] 

Images will be displayed for the fields, thumbNail and detailImage

+16
Sep 25 '15 at
source share

With django-imagekit, you can add any image as follows:

 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' readonly_fields = ['image_display'] # this is for the change form 
+9
Aug 02 '16 at 10:32
source share

Although there are already some good, functional solutions here, I believe that informal markup, such as auxiliary image tags, belongs to templates, and is not tied to widgets of Django forms or generated in model administrative classes. More semantic solution:

Admin Template Override

Note. Obviously, my reputation is not high enough to post more than two simple links, so I created annotations in the following text and included the corresponding URLs at the bottom of this answer.

From the documentation of the Django admin site :

It is relatively easy to override many of the templates that the admin module uses to create various admin site pages. You can even override some of these templates for a specific application or model.

Django django.contrib.admin.options.ModelAdmin (usually accessed in the django.contrib.admin.ModelAdmin namespace) represents a series of possible template paths for the Django template loader in order from most specific to less. This snippet was copied directly from django.contrib.admin.options.ModelAdmin.render_change_form :

 return TemplateResponse(request, form_template or [ "admin/%s/%s/change_form.html" % (app_label, opts.model_name), "admin/%s/change_form.html" % app_label, "admin/change_form.html" ], context) 

Therefore, given the aforementioned documentation on overriding Django admin templates and the search path for templates, suppose you have created the "Articles" application, which defines the "Article" model class. If someone wants to override or expand only the standard form for changing the Django admin site for the articles.models.Article model, you can follow these steps:

  1. Create a template directory structure for the override file.
    • Although this is not mentioned in the documentation, the template loader will first search the application directories if APP_DIRS 1 is set to True .
    • Since someone wants to redefine the Django admin site template by application label and model, the resulting directory hierarchy will look like this: <project_root>/articles/templates/admin/articles/article/
  2. Create a template file in one new directory structure.
    • Only the admin change form should be overridden, so create change_form.html .
    • The final absolute path will be <project_root>/articles/templates/admin/articles/article/change_form.html
  3. Completely override or simply expand the default admin change form template.
    • I could not find any information in the Django documentation regarding contextual data available for standard admin site templates, so I was forced to take a look at the source code for Django.
      • Default change form template: github.com/django/django/blob/master/django/contrib/admin/templates/admin/change_form.html
      • Several relevant context dictionary definitions can be found in django.contrib.admin.options.ModelAdmin._changeform_view and django.contrib.admin.options.ModelAdmin.render_change_form

My decision

Assuming that my name for the ImageField attribute in the model is โ€œfileโ€, my overriding the template to implement image preview would be something like this:

 {% extends "admin/change_form.html" %} {% block field_sets %} {% if original %} <div class="aligned form-row"> <div> <label>Preview:</label> <img alt="image preview" src="/{{ original.file.url }}" style="max-height: 300px;"> </div> </div> {% endif %} {% for fieldset in adminform %} {% include "admin/includes/fieldset.html" %} {% endfor %} {% endblock %} 

original represents the instance of the model from which ModelForm was generated. Also, I usually donโ€™t use inline CSS, but it didnโ€™t cost a separate file for one rule.

Sources:

  1. docs.djangoproject.com/en/dev/ref/settings/#app-dirs
+7
May 22 '17 at 9:46 pm
source share

Here's how it works for django 2.1 without changing models.py :

In your Hero model you have an image field.

 headshot = models.ImageField(null=True, blank=True, upload_to="hero_headshots/") 

You can do it like this:

 @admin.register(Hero) class HeroAdmin(admin.ModelAdmin, ExportCsvMixin): readonly_fields = [..., "headshot_image"] def headshot_image(self, obj): return mark_safe('<img src="{url}" width="{width}" height={height} />'.format( url = obj.headshot.url, width=obj.headshot.width, height=obj.headshot.height, ) ) 
+2
Nov 11 '18 at 5:26
source share

Django 2.1 updates for Venkat Kotra response . The answer works fine on Django 2.0.7 and below. But it gives the server 500 an error (if DEBUG=False ) or gives

render() got an unexpected keyword argument 'renderer'

The reason is because in Django 2.1: Support for Widget.render() methods without the renderer argument is removed. So param renderer now required. We need to update the render() AdminImageWidget to enable the renderer parameter. And this should be after attrs (before kwargs if you have one):

 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(u' <a href="%s" target="_blank"><img src="%s" alt="%s" /></a> %s ' % \ (image_url, image_url, file_name, _('Change:'))) output.append(super(AdminFileWidget, self).render(name, value, attrs, renderer)) return mark_safe(u''.join(output)) 
+1
Aug 21 '18 at 16:18
source share



All Articles