ImageField is the default image uploading field in Django. By default, when you upload an image from Django’s admin panel, it will display the name/URL of the image rather than the picture itself, this post will show you how to show an Image in Django admin after uploading it.
In this post, I use an example of a simple Django e-commerce website with a model Product
that has the product_img
attribute that uses the ImageField field. Below is an example.
models.py
from django.db import models
class Product(models.Model):
name = models.CharField(max_length = 100)
description = models.TextField()
price = models.IntegerField()
product_img = models.ImageField(upload_to = 'images')
And your admin looks like this:
from django.contrib import admin
from .models import Product
admin.site.register(Product)
If you do not understand what is going on in this snippet of code. Let me explain it to you right at this point. But if you do, feel free to jump right to the answer in the following sections.
The Product model represents a table that stores some information about a product. In this case, they are the name, the description, the price, and the product image (which we want its image to be displayed in the admin when we upload it). Of course, this is a very simple model and you might seldom find it in real-world projects as it is.
In the admin.py file, we register the model using admin.site.register(ModelName)
Show Image In Django Admin: Table of Contents
- Prerequisites Before you can Show Image In Django Admin.
- How To Show Image In Django Admin.
- Further Customization.
- Conclusion: How To Show Image In Django Admin.
Prerequisites Before you can Show Image In Django Admin.
- Install Pillow. The recommended method is to run the command
python -m install pillow
in your terminal. - Register the model to the admin, so that we can be able to work with it from the admin panel. Check out How To Register Model In Django Admin to learn more.
- Make migrations, then migrate those changes to the database.
- Create a Superuser to login into the database. Check out How to create Superuser in Django and how to access the admin to learn more.
Once you have the mentioned prerequisites, it’s time to make your Django admin show the image that has been uploaded. But for now, let’s check out what it’s currently doing to see a clear difference afterward.
Run your Django development server using python manage.py runserver
, then go to http://127.0.0.1:8000/admin/
and log in using the superuser credentials you created before. If you have not, check out How To Create Superuser In Django to learn how to do that.
Now once you’re in the admin, click on the model that you want to add information about. In this case, it is the Product model.
Enter all the information you want. The image will be displayed as below.
And right there! That is our problem, as you can see, the admin here is displaying the name of the picture instead of the picture itself. But we want it to show the image. Let’s see how we can do it. For now, just delete the Product object you just created so we can start all over again to avoid disturbances with the database.
How To Show Image In Django Admin.
This is what you have to do:
In your models.py add the picture preview method to the model that has the image.
from django.db import models
from django.utils.html import mark_safe
class Product(models.Model):
name = models.CharField(max_length = 100)
description = models.TextField()
price = models.IntegerField()
product_img = models.ImageField(upload_to = 'images')
def img_preview(self): #new
return mark_safe(f'<img src = "{self.product_img.url}" width = "300"/>')
You can also do it using the older format method
def img_preview(self): #new
return mark_safe('<img src = "{url}" width = "300"/>'.format(
url = self.product_img.url
))
Let me explain what this code is doing; If you do understand, feel free to move on.
On line 12 we define a function called img_preview
that returns an image. How?
By using mark_safe()
which is a method that escapes HTML so that we can write variables inside it. Below is how we would normally display an image in HTML only.
<img src="name_of_image.jpg" width="300">
And this is how we did it with mark_safe()
.
mark_safe(f'<img src = "{self.product_img.url}" width = "300"/>')
Now our variable is the URL because it is going to be different for each instance of the model. But now, how do we pass in the variable. Well, you can choose between two methods: Python f strings or the Python format method. Python f strings are new and the format method is a bit old.
It is usually preferable to specify one dimension of the image to avoid squashing or stretching. In this case, we only specified the width of the image, but you can also do that with height.
Using these methods we pass in the URL argument of the product_img to the HTML.
Register the Model
In your admin, create a new class to register to the admin.
from django.contrib import admin
from .models import Product
class ProductAdmin(admin.ModelAdmin): # new
readonly_fields = ['img_preview']
admin.site.register(Product, ProductAdmin) # new
Now go and check the detail page of one of your models in the admin. You should see another read-only field at the bottom of the page.
The Image will not display at the very instance, you upload it. You first need to save the model, then come back to that model and the image will be displayed.
If the image does not preview, perhaps you need to fix your project level urls.py to allow for the preview of images in debug mode.
If that is the case, use the following snippets of code in their respective files. For more information on this topic, read how to upload images with Django.
In the project-level urls.py file.
from django.contrib import admin
from django.urls import path
from django.conf import settings #new
from django.conf.urls.static import static #new
urlpatterns = [
path('admin/', admin.site.urls),
]
if settings.DEBUG:
urlpatterns += static( settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
This allows us to view static files when DEBUG is set to true, which is during our development period.
In the settings.py file
...
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
At the bottom is a much more favorable place to put this code.
Now every image you upload will be stored in the media/images
folder as we referenced this location in the upload_to
argument with the Imagefield.
Further Customization.
The examples I showed above were just to show how it is done at the most basic level. You can further customize it into more cool stuff.
Show the Image In Django Admin as big as it can get.
In the models.py:
Using Python f strings.
...
def img_preview(self): #new
return mark_safe(f'<img src = "{self.product_img.url}" width = "{self.product.width}" height="{self.product.height}"/>')
Using the Python format method.
...
def img_preview(self): #new
return mark_safe('<img src = "{url}" witdh = "{width}" height="{height}"/>'.format(
url = self.product_img.url
width = self.product.width
height = self.product.height
))
Show Image In Django Admin as Part of the list_display
In the admin.py
from django.contrib import admin
from .models import Product
class ProductAdmin(admin.ModelAdmin): # new
readonly_fields = ['img_preview']
list_display = ['name', 'img_preview']
admin.site.register(Product, ProductAdmin) # new
You can get more creative with this.
Conclusion: How To Show Image In Django Admin.
Thank you for stopping by this post, I hope you were able to follow along and that you found it helpful. If that is the case, please share it with fellow Django developers whom you think will need it. Otherwise, let me know of any problems you encountered along the way, and I’ll be happy to help, See you in other Coding gear articles. Peace.
How can I make images appear in preview when referenced from another model as ForeignKey? I have a model for uploading images and I wanna create a field in another model that’s linked to the image model as a ForeignKey (and another field as ManyToManyField), so I want the image preview to appear inside the admin page of the referencing model, is that possible?
It works well, thanks.
You’re welcome Jorge, I’m glad I could help
It worked for me, thank you
I have a question
Do you have a way to use this method to show images in Many-To-Many-Field ?
Thanks Allen for stopping by.
Unfortunately, I haven’t found a way to show the images in a Many-to-Many field relationship.
But when I do, I’ll definitely add to the post