Skip to content

Instantly share code, notes, and snippets.

@tino
Created August 2, 2015 14:10
Show Gist options
  • Save tino/655f515a56aff1931803 to your computer and use it in GitHub Desktop.
Save tino/655f515a56aff1931803 to your computer and use it in GitHub Desktop.
Using jQuery.guillotine in the Django Admin with Imagekit
window.$ = django.jQuery;
window.jQuery = django.jQuery; // for guillotine
function showCropper(input, output_name, crop_width, crop_height) {
field = $(input);
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('img.cropper').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
$('img.cropper').on('load', function(){
cropper = $(this);
cropper.guillotine({width: crop_width, height: crop_height,
onChange: function(data, action){
$('input[name="' + output_name + '"]')[0].value = JSON.stringify(data);
}
});
// Initial fit
cropper.guillotine('fit');
// Bind button actions
$('#fit').click(function(){ cropper.guillotine('fit'); });
$('#zoom_in').click(function(){ cropper.guillotine('zoomIn'); });
$('#zoom_out').click(function(){ cropper.guillotine('zoomOut'); });
cropper.show();
field.parent().siblings('.cropper-frame').show()
field.parent().siblings('.cropper-buttons').show()
});
}
window.showCropper = showCropper;
import datetime
from django import forms
from django.contrib import admin
from imagekit.admin import AdminThumbnail
from widgets import AdminClearableFileInputWithCrop
from .models import Item
class ItemAdmin(admin.ModelAdmin):
list_display = ('get_title', 'thumbnail', 'content_type',
'content_object', 'is_visible')
fields = ('content_type', 'object_id', 'title', 'subtitle',
'image', 'image_crop_dimensions', 'publication_date')
thumbnail = AdminThumbnail(image_field='admin_thumbnail')
def formfield_for_dbfield(self, db_field, **kwargs):
if db_field.name == 'image':
kwargs['widget'] = AdminClearableFileInputWithCrop
elif db_field.name == 'image_crop_dimensions':
kwargs['widget'] = forms.HiddenInput
return super(ItemAdmin, self).formfield_for_dbfield(db_field, **kwargs)
admin.site.register(Item, ItemAdmin)
from __future__ import unicode_literals
from django.forms.widgets import ClearableFileInput, CheckboxInput
from django.utils.html import conditional_escape
from django.utils.safestring import mark_safe
class ClearableFileInputWithCrop(ClearableFileInput):
template_with_initial = (
'%(initial_text)s: <a href="%(initial_url)s">%(initial)s</a> '
'%(clear_template)s<br />%(input_text)s: %(input)s'
)
template_cropper = (
'<script>django.jQuery(".croppable-file-input").on("change", '
'function(){showCropper(this, "%(cropper_save_field_name)s", %(cropper_width)s, %(cropper_height)s)})</script>'
'<div style="width: 320px; height: 90px; margin-left:10em;" class="cropper-frame hidden">'
'<img src="" class="cropper"></div>'
'<div class="cropper-buttons hidden" style="margin-left:10em;">'
' <button id="zoom_out" type="button" title="Zoom out"> - </button>'
' <button id="fit" type="button" title="Fit image"> [ ] </button>'
' <button id="zoom_in" type="button" title="Zoom in"> + </button>'
'</div>'
)
template_with_initial = template_with_initial + template_cropper
def clear_checkbox_name(self, name):
"""
Given the name of the file input, return the name of the clear checkbox
input.
"""
return name + '-clear'
def clear_checkbox_id(self, name):
"""
Given the name of the clear checkbox input, return the HTML id for it.
"""
return name + '_id'
def is_initial(self, value):
"""
Return whether value is considered to be initial value.
"""
return bool(value and hasattr(value, 'url'))
def get_template_substitution_values(self, value):
"""
Return value-related substitutions.
"""
return {
'initial': conditional_escape(value),
'initial_url': conditional_escape(value.url),
}
def render(self, name, value, attrs=None):
self.attrs['class'] = 'croppable-file-input'
substitutions = {
'initial_text': self.initial_text,
'input_text': self.input_text,
'clear_template': '',
'clear_checkbox_label': self.clear_checkbox_label,
}
template = '<p>%(input)s<br>' + self.template_cropper + '</p>'
substitutions['input'] = super(ClearableFileInput, self).render(name, value, attrs)
substitutions['cropper_save_field_name'] = '%s_crop_dimensions' % name
substitutions['cropper_width'] = getattr(self, 'cropper_width', 320)
substitutions['cropper_height'] = getattr(self, 'cropper_height', 90)
if self.is_initial(value):
template = self.template_with_initial
substitutions.update(self.get_template_substitution_values(value))
if not self.is_required:
checkbox_name = self.clear_checkbox_name(name)
checkbox_id = self.clear_checkbox_id(checkbox_name)
substitutions['clear_checkbox_name'] = conditional_escape(checkbox_name)
substitutions['clear_checkbox_id'] = conditional_escape(checkbox_id)
substitutions['clear'] = CheckboxInput().render(checkbox_name, False, attrs={'id': checkbox_id})
substitutions['clear_template'] = self.template_with_clear % substitutions
return mark_safe(template % substitutions)
class Media:
js = ('js/admin-cropper.js',
'js/vendor/guillotine/jquery.guillotine.js')
css = {
'all': ('js/vendor/guillotine/jquery.guillotine.css',)
}
class AdminClearableFileInputWithCrop(ClearableFileInputWithCrop):
template_with_initial = ('<p class="file-upload">%s</p>'
% ClearableFileInputWithCrop.template_with_initial)
template_with_clear = ('<span class="clearable-file-input">%s</span>'
% ClearableFileInputWithCrop.template_with_clear)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment