Closed koddr closed 6 years ago
In my case, I do it with replace default template and add some JavaScript code.
For example, my models.py
:
# ./example/models.py
class Example(models.Model):
""" Example model """
image = models.ImageField('Picture', default=None)
image_790x160 = ImageSpecField(
source='image',
processors=[ResizeToFill(790, 160)],
format='JPEG',
options={'quality': 85}
)
...
...and admin.py
:
# ./example/admin.py
@admin.register(Example) # Register `Example` as Admin model
class ExampleAdmin(admin.ModelAdmin):
list_display = ('id',)
readonly_fields = ('admin_thumbnail',)
admin_thumbnail = AdminThumbnail(image_field='image_790x160', template='admin/thumbnail.html')
...
...and custom thumbnail template:
<!-- ./templates/admin/thumbnail.html -->
{% if thumbnail %}
<img src="{{ thumbnail.url }}" alt="thumbnail">
{% else %}
<div id="preview_image" style="display: none; width: 790px; height: 160px;"></div>
<script>
function handleFileSelect(event) {
var files = event.target.files; // FileList object
// Loop through the FileList and render image files as thumbnails
for (var i = 0, f; f = files[i]; i++) {
// Only process image files
if (!f.type.match('image.*')) continue;
// Init FileReader()
// See: https://developer.mozilla.org/en-US/docs/Web/API/FileReader
var reader = new FileReader();
// Closure to capture the file information
reader.onload = (function () {
return function (e) {
// Render background image
document.getElementById('preview_image').style.background = 'url(' + e.target.result + ') no-repeat center center';
document.getElementById('preview_image').style.backgroundSize = 'cover';
// Set `display: block` to preview image container
document.getElementById('preview_image').style.display = 'block';
};
})(f);
// Read in the image file as a data URL
reader.readAsDataURL(f);
}
}
// Change background after change file input
// id_image — is default ID for ImageField input named `image` (in Django Admin)
document.getElementById('id_image').addEventListener('change', handleFileSelect, false);
</script>
{% endif %}
P.S. would be nice to add something like my case to official docs of Django ImageKit for future people who search solution for similar things 👍
I think that this is outside of the scope of ImageKit. ImageKit can't work with files which are not saved (not uploaded at all to the server). You have two options:
In the end It all depends on your use case, and general solutions that can be included in ImageKit can be very hard or unneeded.
Hi,Koddr ,I have no idea that where is AdminThumbnail from?Would you please tell me?
Guys, I drop a solution right here anyway, Ha!
1) Define a custom field in the model (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,
})
2) Make it 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',))
3) Define a template for that new field (my_image_thumbnail_template.html):
<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>
@lucasvazq thanks! It's better late than never 😉
@lucasvazq i was searching for a long time thanks anyway.
Hello again!
I search for best practice for preview image in Django admin before save model. I want to display image quickly for my site moderators (with included filter from ImageKit) when they're adding image to the ImageField in admin. This's important, because this images posted to our Instagram account after save model (automatically).
I know about https://github.com/matthewwithanm/django-imagekit#admin but it's way for preview image AFTER save model. I need to BEFORE save...
Can somebody help me understand what to do or/and share their recipes? 👍 Thanks.