Вставлю свои пять копеек о том, насколько классная и гибкая штука — админка 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 использовать эту страницу со списком в качестве файл-менеджера картинок.