0

models.py

class Banner(models.Model):
    banner_photo = models.ImageField(null=True, blank=True)

As the answer below, I would like to preview the image selection before saving the banner image in django-admin. I am a beginner about HTml. How do I override it?

I want to preview the banner picture to be registered with Admin like the captured image. I don't know how to apply it even if I see the answer.

onchange file input change img src and change image color enter image description here

pydjango
  • 37
  • 9
  • I don't believe this is a `Django` question. Given its client-side I'd argue its more `HTML` & `JS`. – PacketLoss Apr 12 '21 at 05:28
  • Does this answer your question? [HTML - Display image after selecting filename](https://stackoverflow.com/questions/12368910/html-display-image-after-selecting-filename) – PacketLoss Apr 12 '21 at 05:28
  • @PacketLoss I want to preview when registering images in django admin, but I knew that I should use HTML & JS when I search on Google. But I don't know HTML & JS well, so I asked how to apply it to django. thank you for your answer. – pydjango Apr 12 '21 at 05:36
  • 1
    Modify the html template for the page you wish to do this on. https://realpython.com/customize-django-admin-python/#overriding-django-admin-templates – PacketLoss Apr 12 '21 at 05:38

1 Answers1

0

I post my answer originally on Github: https://github.com/matthewwithanm/django-imagekit/issues/444

But, I want to share it right here. I think it can help you and someone else.

So, answering your question: yes, it is possible to preview your image before saving it using the Django admin app.

Here are the steps:

  1. Define a custom field in the model that has the image that you want to preview (models.py):
from django.contrib.admin.decorators import display
from django.db.models import Model
from django.db.models.fields.files import ImageField
from django.template.loader import get_template


class MyModel(Model):
    my_image_field = ImageField()

    # This is our new field. It renders a preview of the image before and post save.
    @display(description='Preview')
    def my_image_thumbnail(self):
        return get_template('my_image_thumbnail_template.html').render({
            'field_name': 'my_image_field',
            'src': self.my_image_field.url if self.my_image_field else None,
        })
  1. Make this new field available in the admin config of the app (admin.py):
from django.contrib import admin

from .models import MyModel

admin.site.register(MyModel, fields=('my_image_thumbnail', 'image'), readonly_fields=('my_image_thumbnail',))
  1. Define a html template for that new field (my_image_thumbnail_template.html):
<!-- This template is reusable, so you don't need to create one for each field that you want a thumbnail -->

<img
  <!--
    If there's no image, for example, when we are adding a new instance,
    we can fill the empty image preview with a placeholder image.
    If want to get this placeholder image URL from your static files,
    must load their URL in the `MyModel.my_image_thumbnail` method.
    Here is a thread that shows how to do it: https://stackoverflow.com/questions/11721818
  -->
  src="{% if src %}{{ src }}{% else %}http://atrilco.com/wp-content/uploads/2017/11/ef3-placeholder-image.jpg{% endif %}"
  id="image-thumbnail-{{ field_name }}"
>

<script>
  // Vainilla javascript  (Babel defaults, not ie 11, not ie_mob 11)

  // This function adds an event listener over the input image field (`my_field_image`).
  // If the user edits that field, the preview image will be updated.
  function changeThumbnail() {
    const fieldName = "{{ field_name }}";
    document
      .getElementById(`id_${fieldName}`)
      .addEventListener("change", function (e) {
        const reader = new FileReader();
        reader.onload = function (e) {
          document.getElementById(`image-thumbnail-${fieldName}`).src = e.target.result;
        };
        reader.readAsDataURL(this.files[0]);
      });
  }

  // This function executes a callback when the document is ready.
  // https://stackoverflow.com/questions/9899372
  //
  // Is this required?
  // No, but, in most cases, the image preview is rendered above the input field,
  // as we do in the `admin.py` module.
  // In that case, need to wait for the document to be ready before adding the
  // event listener defined in `changeThumbnail`.
  function docReady(fn) {
    if (document.readyState === "complete" || document.readyState === "interactive") {
      setTimeout(fn, 1);
    } else {
      document.addEventListener("DOMContentLoaded", fn);
    }
  }
   docReady(changeThumbnail);
</script>

Result

New model instance without image

New instance without image

New model instance with image

New instance with image

For the curious: I use django-jazzmin (custom Django admin theme)

Lucas Vazquez
  • 1,456
  • 16
  • 20