вторник, 20 сентября 2011 г.

Добавляем свои кнопки в админку Django

Есть у меня такая привычка - редактировать html-код вручную. При написании новых статей на своем сайте я всегда делал разметку вручную, но однажды решил попробовать wysiwyg-редактор tinymce. Это хороший редактор, но мне он не подошел. Он делал много лишнего и не делал кое-чего нужного. Я не буду расписывать причины, по которым я от него отказался, т.к. это заняло бы слишком много места. Скажу лучше, как добавить в админку django несколько своих кнопок и повесить на них простые действия - обрамление выделенного текста в html-теги. Впрочем, вместо кнопок можно добавить все, что угодно.



Если вы хотите немного изменить админку джанго и добавить в нее свой функционал, не обязательно редактировать файлы джанго. Можно просто интегрироваться в ее шаблоны.

К примеру, есть у меня приложение 'articles', которое я использую для создания статей. Я хочу добавить на страницу создания/изменения статьи свой код. Для этого нужно создать в каталоге ваших шаблонов файл "templates/admin/articles/change_form.html". Имя каталога "articles" означает, что изменения нужно делать для приложения с таким же именем. Имя файла - "change_form.html" поидее может быть любым. Нужно добавить в этот файл следующий код:

{% extends “admin/change_form.html” %}
{% load i18n %}
{% block object-tools %}
<h1>Hey!</h1>
{% endblock %}

Теперь зайдите в админку в приложение 'articles' (или как там оно у вас называется) и вверху страницы сможете обнаружить надпись "Hey!".

Изменять таким образом можно не все шаблоны админки. Вот список шаблонов, которые можно изменять:
  • app_index.html
  • change_form.html
  • change_list.html
  • delete_confirmation.html
  • object_history.html

Собственно на этом можно было бы закончить. Но раз уж я описываю пример добавления своих кнопок в джанго админку, то расскажу, как это сделать. На странице создания/редактирования статей у меня есть поле textarea (text = models.TextField() в файле articles/models.py). Чтобы было удобнее, свои кнопки надо добавить сразу после этого поля (они будут прямо под ним). Тут нам поможет jquery (как его добавлять в джанго, гуглите отдельно). 

В jquery есть удобные функции append, before и after, которые позволяют добавлять текст-код в, перед и после определенных элементов. Чтобы понять, как это работает, вот вам простой пример:

<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js“></script>
</head>
<body>

<h1></h1>
<p>Привет,  </p>
<p id=”text“>Я хотел тебе что-то сказать, но передумал.</p>
<span class=”bye“>Пока, </span>

<script>
$(”h1“).append(”Заголовок“)
$(”p:first“).append(”Человек“);
$(”#text“).before(”<hr>“);
$(”.bye“).append(”Человек“);
$(”.bye“).after(”<hr>");
</script>

</body>
</html>


Просто сохраните это в html-файле и откройте браузером. Пояснять не буду, все и так понятно.

Чтобы добавить текст после каждого поля textarea (а у меня оно одно) риведите наш файл change_form.html к такому виду:

{% extends “admin/change_form.html” %}
{% load i18n %}
{% block object-tools %}
        <script type=“text/javascript” charset=“utf-8”>
                (function($) { $(document).ready(function() {
                                        $(“textarea”).after('<h1>Hey</h1>');
                });
                })(django.jQuery);
        </script>
{% endblock %}



Итак, мы добавили текст  в определенное место на странице. Теперь сделаем что-нибудь полезное. Как я уже говорил, мне предпочтительнее делать простую разметку текста вручную. Поэтому добавим кнопку, по нажатию на которую выделенный в textarea текст будет обрамляться в тег strong. Приведите файл change_form.html к такому виду:


{% extends “admin/change_form.html” %}
{% load i18n %}
{% block object-tools %}
        <script type=“text/javascript” charset=“utf-8”>
                (function($) { $(document).ready(function() {
                $(“textarea”).after('<br><input type=“button” value=“Strong” onclick=“add_tags(\'<strong>\',\'</strong>\')”>');
                });
                })(django.jQuery);
        </script>
        <script type=“text/javascript” charset=“utf-8”>
                             function add_tags(str1, str2)
                             {
                            var obj=document.getElementById(“id_text”);
                            obj.focus();
                            
                            if(document.selection)
                            {
                               var s = document.selection.createRange();          
                               s.text = str1 + s.text + str2;                
                            }else
                            {
                               var len = obj.value.length;
                               var start = obj.selectionStart;
                               var end = obj.selectionEnd;
                         
                               var scrollTop = obj.scrollTop;
                               var scrollLeft = obj.scrollLeft;
                         
                               var sel = obj.value.substring(start, end);
                               var rep = str1 + sel + str2;
                               obj.value =  obj.value.substring(0,start) + rep + obj.value.substring(end,len);
                         
                               obj.scrollTop = scrollTop;
                               obj.scrollLeft = scrollLeft;  
                            }
                         }
        </script>
{% endblock %}


По аналогии можно добавить и другие кнопки.
Вот и все. Прошу прощения за скомканное изложение.

11 комментариев:

  1. Что-то не очень понятно с путями, у меня есть проект на django 1.3.1, но сам django не лежит рядом с приложением. Я создал change_form.html с этим текстом, приложение тоже называется articles, путь такой: "". Куда в моём случае надо положить файл? Пробовал как в статье - никаких результатов.

    ОтветитьУдалить
  2. Куда-то путь пропал из предыдущего сообщения: папка_проекта/articles.

    ОтветитьУдалить
  3. У вас есть каталог, в котором лежат шаблоны проекта (указывается в settings.py). Обычно, это каталог templates/. В нем создаете такую структуру admin/имя_приложения/change_form.html . Это если нужно подменить change_form.html для конкретного приложения. Если нужно для всех, то просто admin/change_form.html. Суть в том, что вы просто берете из джанги файл change_form.html (или какой-нибудь другой) и кладете его в каталог шаблонов проекта и использоваться будет он. Вы можете и напрямую отредактировать файл прямо в каталоге джанго /usr/lib/python/site-packages/django/bla/bla/ , но в таком случае при обновлении джанго изменения затрутся.

    ОтветитьУдалить
  4. Аааа, видать, оно и с первого раза сработало, просто я не туда смотрел. ))) Кстати, в статье у абзацев разные шрифты.

    ОтветитьУдалить
  5. Этот комментарий был удален автором.

    ОтветитьУдалить
  6. Этот комментарий был удален автором.

    ОтветитьУдалить
  7. Не очень ясен смысл:
    var scrollTop = obj.scrollTop;
    var scrollLeft = obj.scrollLeft;
    obj.scrollTop = scrollTop;
    obj.scrollLeft = scrollLeft;
    поскольку прокрутки к этим позициям всё равно не происходит.
    А можно ли сделать так, чтобы после добавления тега выделение текста оставалось (как вариант, тот кусок текста выделялся заново), или в крайнем случае каретка устанавливалась перед закрывающим тегом?

    ОтветитьУдалить
    Ответы
    1. Я этот код, по-моему, откуда-то скопировал, что-то ненужное вырезал, а что-то лишнее осталось :) По вашему вопросу про выделение текста сейчас ничего в голову путного не приходит что-то.

      Удалить
  8. Нашёл статью, как интегрировать CKEditor в django, буду пробовать. :)

    ОтветитьУдалить
  9. Всё получилось, http://linuxtime.org/article/2/
    Были проблемы, решил тут: http://djbook.ru/forum/topic/527/ и тут: http://djbook.ru/forum/topic/530/

    ОтветитьУдалить