Вставлю свои пять копеек о том, насколько классная и гибкая штука — админка Django. Многие упорно не хотят понять, что это не игрушка, а вполне себе приложение production-качества, которое просто глупо не использовать, если есть такая возможность.
И дело здесь совсем не в том, что разработчики такие молодцы, что предусмотрели так много возможностей кастомизирования, чтобы покрыть все нужды юзеров — это конечно же не совсем так. Тем не менее в распоряжении разработчика всегда есть другое мощнейшее средство кастомизации любых веб-приложений вообще. Таким средством является Javascript. Разработчики Django, прекрасно это осознавая, предоставляют нам все средства для подключения кастомного JS/CSS, что по сути, вобще снимает какие-либо ограничения на то, что мы хотим слепить из нашей админки.
Конечно в этом нет ничего военного и большинство опытных разработчиков так и делают, я лишь попытаюсь описать парочку жизненных рецептов, на основании которых можно, подключив немного фантазии, решать практически любые вопросы связанные с кастомизированием Django-админки. Если конкретнее, то заниматься будем тем, что сделаем акуратные thumbnails для наших ImageField'ов, подключим TinyMCE, и научим его вставлять картинки используя саму Django-admin в качестве файл-менеджера для выбора картинок.
Итак предположим, что мы хотим взять обычные flatpages и дополнить их возможностью создавать страницы с помощью WYSIWYG-редактора, в том числе заливать и вставлять картинки (что за страницы без картинок?)
Для начала создадим простую модель FlatPicture и научим её делать thumbnails. Для этого воспользуемся библиотекой PIL (стандартнее некуда). С её помощью создавать thumbnails не просто, а очень просто. Всю логику работы с thumbnails вынесем в отдельный файл (да-да все 10 stupid simple строчек)
Эти функции нам очень пригодятся для того, чтобы прикрутить thumbnails к нашей модели:
Вот так вот дёшево и сердито у нас уже автоматически создаются и удаляются thumbnails нужного нам размера. Хотя стоит только бросить взгляд на форму редактирования и список картинок, как становится очевидно что чего-то явно не хватает…

… Конечно же и в списке и на форме хочется видеть thumbnail текущей картинки, а не догадываться по названию что там. Таким образом плавно подходим к теме этого поста. Нет, нам не нужно переопределять десяток шаблонов и писать новые виджеты. На помощь нам придёт Javascript.
Для наглядности я использую jQuery, подлючаю его (вместе с TinyMCE) опять же stupid simple — переопределив шаблон 'admin/base_site.html'. Это довольно удобно подключить эти библиотеки один раз «глобально», если они у вас используются по всей админке:
C задачей отображения thumbnail в списке нам поможет справиться метод 'get_thumbnail_html', который мы ужепредусмотрительно добавили в модель. А для того чтобы отобразить thumb на форме, нам понадобится следующий JS, который можно будет впоследствии подключать к любой форме, для которой понадобится такая функциональность:
Теперь лёгким движением руки добавляем оба этих элемента в 'admin.py'…
… и любуемся на результат:

На этом пока всё. В следующей серии о том, как заставить TinyMCE использовать эту страницу со списком в качестве файл-менеджера картинок.
И дело здесь совсем не в том, что разработчики такие молодцы, что предусмотрели так много возможностей кастомизирования, чтобы покрыть все нужды юзеров — это конечно же не совсем так. Тем не менее в распоряжении разработчика всегда есть другое мощнейшее средство кастомизации любых веб-приложений вообще. Таким средством является Javascript. Разработчики Django, прекрасно это осознавая, предоставляют нам все средства для подключения кастомного JS/CSS, что по сути, вобще снимает какие-либо ограничения на то, что мы хотим слепить из нашей админки.
Конечно в этом нет ничего военного и большинство опытных разработчиков так и делают, я лишь попытаюсь описать парочку жизненных рецептов, на основании которых можно, подключив немного фантазии, решать практически любые вопросы связанные с кастомизированием Django-админки. Если конкретнее, то заниматься будем тем, что сделаем акуратные thumbnails для наших ImageField'ов, подключим TinyMCE, и научим его вставлять картинки используя саму Django-admin в качестве файл-менеджера для выбора картинок.
Итак предположим, что мы хотим взять обычные flatpages и дополнить их возможностью создавать страницы с помощью WYSIWYG-редактора, в том числе заливать и вставлять картинки (что за страницы без картинок?)
Для начала создадим простую модель FlatPicture и научим её делать thumbnails. Для этого воспользуемся библиотекой PIL (стандартнее некуда). С её помощью создавать thumbnails не просто, а очень просто. Всю логику работы с thumbnails вынесем в отдельный файл (да-да все 10 stupid simple строчек)
#utils.py
import os
from PIL import Image
def get_thumbnail_url(image_url, size=150):
thumbs_part = 'thumbs_' + str(size)
image_url_parts = image_url.rsplit('/', 1)
return image_url_parts[0] + '/' + thumbs_part + '/' + image_url_parts[1]
def get_thumbnail_path(image_path, size=150):
thumbs_dir = 'thumbs_' + str(size)
dirname, filename = os.path.split(image_path)
dirname = os.path.join(dirname, thumbs_dir)
if not os.path.exists(dirname):
os.mkdir(dirname, 0755)
return os.path.join(dirname, filename)
def create_thumbnail(image_path, size=150):
thumb_path = get_thumbnail_path(image_path, size)
delete_thumbnail(image_path, size)
img = Image.open(image_path)
img.thumbnail((size, size), Image.ANTIALIAS)
img.save(thumb_path)
def delete_thumbnail(image_path, size=150):
thumb_path = get_thumbnail_path(image_path, size)
if os.path.exists(thumb_path):
os.remove(thumb_path)Эти функции нам очень пригодятся для того, чтобы прикрутить thumbnails к нашей модели:
from django.db.models.signals import post_save, pre_delete
from utils import *
class FlatPicture(models.Model):
picture = models.ImageField(upload_to='uploads/flatpictures', max_length=250)
description = models.CharField(max_length=250, blank=True)
def get_thumbnail_html(self):
html = '<a class="image-picker" href="%s"><img src="%s" alt="%s"/></a>'
return html % (self.picture.url, get_thumbnail_url(self.picture.url), self.description)
get_thumbnail_html.short_description = _('thumbnail')
get_thumbnail_html.allow_tags = True
def post_save_handler(sender, **kwargs):
create_thumbnail(kwargs['instance'].picture.path)
post_save.connect(post_save_handler, sender=FlatPicture)
def pre_delete_handler(sender, **kwargs):
delete_thumbnail(kwargs['instance'].picture.path)
pre_delete.connect(pre_delete_handler, sender=FlatPicture)Вот так вот дёшево и сердито у нас уже автоматически создаются и удаляются thumbnails нужного нам размера. Хотя стоит только бросить взгляд на форму редактирования и список картинок, как становится очевидно что чего-то явно не хватает…

… Конечно же и в списке и на форме хочется видеть thumbnail текущей картинки, а не догадываться по названию что там. Таким образом плавно подходим к теме этого поста. Нет, нам не нужно переопределять десяток шаблонов и писать новые виджеты. На помощь нам придёт Javascript.
Для наглядности я использую jQuery, подлючаю его (вместе с TinyMCE) опять же stupid simple — переопределив шаблон 'admin/base_site.html'. Это довольно удобно подключить эти библиотеки один раз «глобально», если они у вас используются по всей админке:
{% extends "admin/base.html" %}
{% load i18n %}
{% block title %}{{ title }} | Админка example.com{% endblock %}
{% block branding %}
<h1 id="site-name">Админка example.com</h1>
{% endblock %}
{% block nav-global %}{% endblock %}
{% block extrastyle %}
<script type="text/javascript" src="/media/lib/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="/media/lib/tiny_mce/jquery.tinymce.js"></script>
<script type="text/javascript" src="/media/js/admin/base.js"></script>
{% endblock %}C задачей отображения thumbnail в списке нам поможет справиться метод 'get_thumbnail_html', который мы уже
$().ready(function() {
$('a[target=_blank]').each(function() {
if ($(this).html().indexOf('uploads/') == 0) {
var path = $(this).attr('href');
path = path.substring(0, path.lastIndexOf('/'))
+ '/thumbs_150'
+ path.substring(path.lastIndexOf('/'));
$(this).parent().after('<a style="margin-left: 10em" href="'
+ $(this).attr('href') + '" target="_blank"><img src="'
+ path + '" alt="image"/></a>');
}
});
});Теперь лёгким движением руки добавляем оба этих элемента в 'admin.py'…
class FlatPictureAdmin(admin.ModelAdmin):
class Media:
js = ['js/admin/display_thumbs.js']
list_display = ['get_thumbnail_html', '__unicode__', 'description']
list_display_links = ['__unicode__']
admin.site.register(FlatPicture, FlatPictureAdmin)… и любуемся на результат:

На этом пока всё. В следующей серии о том, как заставить TinyMCE использовать эту страницу со списком в качестве файл-менеджера картинок.
