Пользователь
0,0
рейтинг
8 июля 2010 в 08:51

Разработка → Улучшаем админку

Одно из слабых мест джанго-админки — главная страница. Идея авто-группировки моделей по приложениям и вывод столбиком в одну колонку работает только на начальных этапах, дальше это становится просто неудобно — куча лишней информации и довольно сложные пути для того, чтобы добавить полезную. Ну, например, чтобы названия приложений писались русскими буквами — полностью перекрывать шаблон.

И тут на помощь приходит django-admin-tools. С этим приложением минут за 20 можно получить «приборную панель» с произвольной группировкой приложений/моделей, вкладками, любым числом колонок, различными блоками, которые каждый пользователь сможет расставить, как ему удобнее, скрывать и сворачивать по желанию, закладками, настраиваемым меню и удобным способом добавления во все это хозяйство всего, чего только можно придумать.

Вот так, например, сейчас выглядит админка к сайту НадоВместе:

image
(это только часть, вот скриншот целиком)

Разберемся поподробнее.

Установка


1. pip install -e hg+http://bitbucket.org/izi/django-admin-tools/#egg=django-admin-tools
Ставим дев-версию, т.к. я фанат дев-версий там много новых вкусных штук: например, упрощен API и добавлены группы. Если не установлен mercurial, то можно скачать последнюю ревизию архивом, распаковать и запустить python setup.py install.

2. Добавляем admin_tools в INSTALLED_APPS (обязательно до django.contrib.admin):

INSTALLED_APPS = (
    'admin_tools',
    'admin_tools.theming',
    'admin_tools.menu',
    'admin_tools.dashboard',    
    # ...
    'django.contrib.auth',
    'django.contrib.sites',
    'django.contrib.admin'
    # ... и другие приложения ...
)

3. python manage.py syncdb

4. подключаем в urls.py:

urlpatterns = patterns('',
    url(r'^admin_tools/', include('admin_tools.urls')),
    #... и т.д. ...
)

5. копируем медиа-файлы (js, css и картинки) в MEDIA_ROOT проекта. Что-то вроде этого — вы ведь используете virtualenv?

cp -r /home/kmike/envs/nadovmeste/src/django-admin-tools/admin_tools/media/admin_tools /path/to/yourproject/media/

Можно вместо копирования сделать симлинк или использовать django-static-files.

Все, можно зайти в админку и удивиться страшной пятнистой шапке тому, как все поменялось. Установка, как видите, вполне обычная, никаких джанговских файлов заменять не нужно (как в grappelli было когда-то).

Блоки


Самая полезная штука в django-admin-tools — это, конечно, блоки. Вы можете настроить, какие блоки и как показывать на заглавной странице, писать свои блоки и брать готовые.

1. Создаем заготовку для «приборной панели»:

python manage.py customdashboard

После этого в корне проекта появится файл dashboard.py с заготовкой. Можно его, в принципе, и руками написать.

В файле будет содержаться 2 класса: CustomIndexDashboard и CustomAppIndexDashboard — для главной страницы админки и страницы отдельного приложения. Нас тут будет интересовать класс CustomIndexDashboard.

2. Указываем в settings.py, что будем использовать свою «приборную панель» на заглавной странице админки:

ADMIN_TOOLS_INDEX_DASHBOARD = 'yourproject.dashboard.CustomIndexDashboard'

3. Для примера: объединим в одном блоке стандартные джанговские модели из auth и свои данные о профайлах, назвав при этом блок по-русски:

from admin_tools.dashboard import modules, Dashboard

class CustomIndexDashboard(Dashboard):

    def __init__(self, **kwargs):
        Dashboard.__init__(self, **kwargs)
        self.children.append(
            modules.ModelList(
                title = u'Пользователи',
                models=(
                    'django.contrib.auth.*',
                    'my_accounts.models.Profile',
                ),
            )
        )


В списке моделей указываются полные пути к моделям, которые требуется подключить. Все модели, которые перечислены в models, должны быть зарегистрированы в джанговской админке как обычно. Если моделей несколько, то можно их все не перечислять, т.к. есть поддержка *. Если вы включили кучу моделей через * и нужно из них убрать несколько, то есть симметричный параметру models параметр exclude со списком моделей, которые показывать не нужно (там тоже есть поддержка *).

Стандартные блоки


django-admin-tools включает в стандартную поставку несколько готовых блоков для приборной панели. Детальную информацию о них можно найти в документации. Тут будет просто краткий обзор + описание замечательного modules.Group, которого не было в документации на момент написания статьи.

Импортировать их следует так: from admin_tools.dashboard import modules

1. modules.ModelList — как мне кажется, это самый основной и полезный блок. Позволяет группировать произвольные модели в рамках одного блока.

image

2. modules.Group — еще один супер-полезный блок. Позволяет группировать любые другие блоки внутри себя. Блоки могут или располагаться друг над другом, или в виде «аккордеона», или во вкладках. Очень удобно, например, для графиков, или для отделения основных и часто используемых разделов от побочных.

image

Пример использования:

        self.children.append(modules.Group(
            title=u"Статистика",
            display="tabs",
            children=[
                nadovmeste_modules.Overview(),
                nadovmeste_modules.Subscribers(),
                nadovmeste_modules.Finances(),
                nadovmeste_modules.Users(),
            ]
        ))


В списке children можно указывать любые другие блоки, в.т.ч. разных типов. В примере тут не стандартные модули из admin_tools.dashboard.modules, а свои (о том, как их делать — позже).

Поддержки вложенных групп пока нет (а если точнее, то сейчас js при этом работает неправильно).

3. modules.LinkList — список произвольных ссылок. Внешние ссылки могут помечаться специальной иконкой, ссылки могут располагаться как горизонтально, так и в столбик.

image

4. modules.AppList — по сути, аналог главной страницы стандартной джанговской админки. Список приложений и моделей в них. Скажу по секрету, тут есть еще не документированный параметр models, который абсолютно аналогичен этому параметру в modules.ModelList — с той разницей, что потом модели будут сгруппированы по приложениям. Этот блок полезен, если хочется добавить все по-быстрому, или повторить обычную джанговскую админку — в остальных случаях, как мне кажется, лучше подходит ModelList. Хотя может это дело вкуса.

5. modules.RecentActions — список последних действий, как в стандартной джанговской админке. Не знаю, зачем он нужен :)

6. modules.Feed — позволяет показывать ленты RSS в админке.

Пишем свои блоки


Напишем, например, абсолютно бесполезный блок, который будет просто выводить какое-то сообщение, переданное ему в конструкторе.

1. Наследуемся от admin_tools.dashboard.modules.DashboardModule:

class MyModule(modules.DashboardModule):
    def is_empty(self):
        return self.message == ''

    def __init__(self, **kwargs):
        super(MyModule, self).__init__(**kwargs)
        self.template = 'my_blocks/hello.html'
        self.message = kwargs.get('message', '')


2. Делаем шаблон templates/my_blocks/hello.html

{% extends "admin_tools/dashboard/module.html" %}
{% block module_content %}
    <h4>{{ module.message  }}</h4>
{% endblock %}


Как видите, объект модуля передается в шаблон. Это означает, что можно передавать любые данные через его атрибуты (что мы и сделали в примере с message).

3. Подключаем блок в dashboard.py

self.children.append(MyModule(title=u"Приветствие", message = u'Привет!'))


Все, готово. Думаю, теперь понятно, как делать любые более сложные штуки, рисовать в блоках графики и тд. Готовим данные, делаем шаблон. Если в контексте шаблона нужен request, то переопределяйте метод init_with_context (по ссылке — пример).

Полученный блок можно будет таскать мышкой, сворачивать-разворачивать, располагать отдельно или во вкладке у modules.Group и тд. — наравне со стандартными блоками.

Да, еще, если нужно что-то просто дописать сверху или снизу стандартного блока, то можно свой блок/шаблон не делать, а воспользоваться атрибутами модуля pre_content и post_content.

Внешний вид


Люди достаточно осторожно подошли к дизайнерству, и новые элементы смотрятся вполне органично рядом со стандартными джанговскими. Но если вам тоже не нравится ненужный заголовок и кошмарная пятнистая стандартная шапка из django-admin-tools, то их проще всего убрать с помощью css. Хорошо бы еще логотип в шапку добавить. Заодно и с тем, как делать темы, разберемся.
image

1. Делаем css-файл со своей темой. Для примера можно посмотреть тему, которая используется в нашей админке, еще пример есть в стандартной поставке.

2. Подключаем файл с темой: в settings.py добавляем настройку
ADMIN_TOOLS_THEMING_CSS = 'css/theming.css' # путь относительно MEDIA_ROOT


Что дальше


В статье нет ничего про меню, закладки, настройку собственно приборных панелей, про панели для отдельных приложений. Обо всем этом можно почитать в документации. Если хотите помочь проекту, подключившись к разработке — welcome. Если что не работает в django-admin-tools, то это я все сломал, если что-то сделано круто — напишите весточку David Jean Louis.

Небольшие хитрости


Если вы обновили модули в своей приборной панели (добавили, удалили, поменяли местами), и после этого все куда-то уехало, то удалите записи из DashboardPreferences.

Статистика на скриншоте — с тестового сервера, реальные данные nadovmeste.ru не «спалил». Если интересно, то в следующей статье расскажу, как заполнять базу большим количеством тестовых данных, и как строк за 5 кода (включая шаблон) получать любые графики со статистикой (как, например, на скриншоте — график со статистикой регистраций пользователей по дням).

Да, спасибо obiwanus и leoglu за ценные замечания на этапе подготовки статьи.
Коробов Михаил @kmike
карма
333,7
рейтинг 0,0
Пользователь
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (45)

  • +4
    Очень полезная статья, как раз занимаюсь пилением админки… спасибо вам за описание…
  • +1
    Очень здорово и красиво. Есть ещё django-grappelli(http://code.google.com/p/django-grappelli/wiki/screenshots).

    Тут главный вопрос — в совместимости с django reusable app, которые рассчитаны на стандартный интерфейс, например django-cms, приходилось допиливать для нормальной интеграции с grappelli.
    • 0
      Про граппелли в статье упоминается. По крайней мере раньше (не знаю, как сейчас) его прикручивание было гораздо менее удобно.
      • +1
        тот же самый процесс: pip install django-grappelli, правим settings.py,urls.py, syncdb и поехали.
        • +1
          Я видимо застал еще то время, когда нужно было обычные медиа-файлы от админки полностью заменить на те, что в grappelli, поэтому так написал.
    • +1
      у django-admin-tools с совместимостью должно быть гораздо лучше, чем у grappelli, т.к. переделка шаблонов и стилей менее кардинальная. Grappelli практически все шаблоны и стили заменили на свои, в django-admin-tools стандартные стили с небольшими доделками.

      Кстати, план ребят из grappelli — использовать django-admin-tools в качестве «дэшборда» ко всему остальному. См. bitbucket.org/fetzig/grappelli-admin-tools/overview
  • +2
    Отличная статья
  • 0
    Спасибо за статью. С интересом, жду продолжения.
  • +1
    Даже не знал что такое возможно, буду пробовать, спасибо!
  • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      Давайте еще о Зенд фреймворке поговорим :)
  • 0
    Про графики было бы интересно почитать.
    • 0
      Мне кажется это обычные DIV-ы с кастомным style=«height»
  • 0
    Ошибку кажет:
    In template /Library/Python/2.6/site-packages/django_admin_tools-0.2.0-py2.6.egg/admin_tools/menu/templates/admin/base_site.html, error at line 17
    13
    14 {% block nav-global %}
    15 {% if user and user.is_authenticated %}
    16 {% if not is_popup %}
    17 {% admin_tools_render_menu %}
    18 {% endif %}
    19 {% endif %}

    админ-тулз устанавливал просто через easy_install
    За статью большое спасибо, этих возможностей нехватало для такой хваленой Джанго-админки.
    • +1
      посмотрите в settings на TEMPLATE_CONTEXT_PROCESSORS там должна быть строчка 'django.core.context_processors.request'

      у меня из-за ее отсутствия ошибка была
      • 0
        Спасибо, помогло!
      • НЛО прилетело и опубликовало эту надпись здесь
        • 0
          А можно подробности почему?
  • +2
    Как же досадно видеть такую лень (или несообразительность).
    На сайте проекта есть скриншоты админки.
    Вот один из них: www.izimobil.org/django-admin-tools/images/capture-2-small.png
    Казалось бы, сверни свой браузер, установи нужную ширину, получи нормальную картинку, которая влезает на страницу без уменьшения. Но увы.
    • 0
      спасибо за замечание, Жан-Луи все поправил)
  • +7
    В кои-то веки авторская статья в стиле «того» хабра, а не репост новости, унылый перевод или очередное изобретение колеса. Спасибо.
    • +4
      kmike еще торт
  • 0
    михаил, как всегда, пишет отличные статьи, спасибо ему за это.

    как раз недавно мучал стандартную админку, вывернул ей все кишки, было очень неудобно) теперь кастомизация будет проходить гораздо приятнее.
  • 0
    Спасибо, попробую )
    • 0
      Уж извольте, попробуйте)
  • 0
    кстати, в одной буржуйской презентации по кастомизации админки, наряду с грапелли видел ссылки на проекты github.com/ella/ella и gondolacms.com/
    кто-нить с такими игрался?
  • 0
    Пишет «Caught an exception while rendering: Reverse for 'admin-tools-dashboard-set-preferences' with arguments '()' and keyword arguments '{}' not found.» В чём может быть причина?
    • 0
      Закомментировал у себя строку
      url(r'^admin_tools/', include('admin_tools.urls')),
      из urls.py, выпала ровно эта же ошибка. Вы не подключили значит url'ы.
      • 0
        Извените, как говориться, нужно внимательней читать. Спасибо большое!
  • 0
    Большое спасибо за статью, как раз искал нечто подобное. Теперь все работает прекрасно.
  • 0
    Очень интересно, спасибо!

    А не знаете, можно ли с помощью этой штуки удалить дурацкие ссылки «Изменить» рядом с каждой моделью?
    • +1
      Код этой дурацкой ссылки — Изменить

      Пропишите для главной страницы свой класс и можете указать в css
      .yourclass .changelink { display: none }

      Это можно сделать и без «этой штуки».
      • +1
        Чорт, код убрался. Читайте:

        Код этой дурацкой ссылки —
        <a class="changelink" ...>Изменить</a>
        • 0
          Спасибо! Думал есть более православный метод :)
          • 0
            Там в начале статьи написано что для админки не очень много православних методов)
          • 0
            А вообще я лох. Есть православный метод — создаешь в папке шаблонов папку admin и копируешь туда файл index.html из django.contrib.admin.templates.

            В файле index.html есть такой код:
                        {% if model.perms.change %}
                            <td><a href="{{ model.admin_url }}" class="changelink">{% trans 'Change' %}</a></td>
                        {% else %}
                            <td> </td>
                        {% endif %}
            

            Просто его удаляешь и все.
  • 0
    Очень красиво. Честно говоря, даже не думал, что из этой довольно жесткой штуки можно сделать такую конфетку.
  • 0
    Скажите, чем вы рисовали такие симпатичные графики?
  • 0
    Тем кто будет впоследствии это читать habrahabr.ru/blogs/python/105627/ — про граффики и пр.
  • 0
    Хотел скачать переводы с transifex, че-т не получается (ссылка не активна). В чем может быть проблема?
    • 0
      Не знаю, а зачем скачивать переводы с transifex?
  • 0
    Оффтоп. Сейчас nadovmeste.ru (kupikupon) сделан на drupal, если не ошибаюсь. Почему решили перейти?
    • 0
      Там никто не переходил, а скорее наоборот: КупиКупон уже был большим и на друпале, когда купил НадоВместе, выкидывать свой движок и менять команду разработчиков они не стали, тут их вполне можно понять, технологии — это далеко не все.

      Мы в итоге с их программистами посидели и аккаунты джанговских пользователей в друпал проэкспортировали, НадоВместе поработал потом еще пару месяцев в полузакрытом режиме (пока срок действия всех купонов не закончился — ну чтоб люди распечатать их могли), и тогда уже редирект сделали окончательно.
  • 0
    Ребята в чем может быть проблема, админка «кривит»: imm.io/QlVn
    Грешил на то что не подгружаются некоторые .css/.js, но вроде все в норме, dev сервер не говорит об 404-ой ошибке
  • 0
    очередная чудовищная джанго свистоподелка
    смотришь на такую и не видишь отличия от того как пхпник пытается встроить google/jquery плагин в уже работающую страницу на MooTools
    то-есть для него, для тупого как молоток аникея, невдомёк, что это разные вещи, для него это просто какие то файлы и он считает, что если их побольше натолкать в свой код то всё будет прекрасно работать
    так и этот модуль, впрочем как большинство джангосвистелок
    посмотрите как он включается в проект, не через import не через from
    а просто, через парсинг INSTALLED_APPS
    а как управляется и расширяется, конечно же точно так же, через парсинг строк
    вот точно такой же подход как этих тупых аникеев, которые копипастят со всяких форумов JS вставки в свой код
    ни какого понимания и даже желания понимать как это работает, только бы побыстрее хоть чтото заработало
    а проходит код, два, три и при очередном обновлении что-то как всегда ломается или Django или в её поделочных модулях и всё, парсинг строк ни как не локализует ошибку, а джанга после того как напарсилась текста досыта, попыталась загрузить, не получилось и она летит дальше, лишь бы у тупого аникея поскорее хоть что-то запустилось, лишь он чувствовал что он что-то может, лишь бы он не думал сам

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.