Django Grappelli Tabular Inline добавить новую строку Текстовое поле TinyMCE недоступно для редактирования - PullRequest
12 голосов
/ 21 апреля 2011

Я использую скин Джанго Граппелли для своего проекта.

У меня есть ModelAdmin с табличной встроенной функцией.

Я использую extra = 0 для предотвращения автоматической вставки пустой строки при загрузке страницы. Работает нормально.

Теперь, когда я нажимаю на знак +, чтобы вставить новую строку, строка загружается, но текстовое поле tinymce недоступно для редактирования.

Кто-нибудь знает, в чем причины и как решить эту проблему?

После прочтения документа:

http://django -grappelli.readthedocs.org / ен / последний / customization.html # с использованием-TinyMCE

замечаю:

Использование TinyMCE с Inlines немного сложнее из-за скрытой пустой формы. Вам необходимо написать собственный шаблон и использовать встроенные обратные вызовы для

onInit: удалить экземпляры TinyMCE из пустой формы.

onAfterAdded: инициализировать экземпляры TinyMCE из формы.

onBeforeRemoved: удалить экземпляры TinyMCE из формы.

TinyMCE с Inlines не поддерживается по умолчанию.

Любой образец для этого? Я заметил, что это функции TinyMCE, которые мне нужно изменить.

Ответы [ 2 ]

14 голосов
/ 29 октября 2013

Похоже, что некоторые классы CSS и HTML-структуры, используемые Grappelli, претерпели изменения с момента написания решения Almflm. Однако мне удалось изменить решение hir для работы с Grappelli v2.4.7 и упростить реализацию в процессе.

Настройка

  1. Переопределите соответствующий шаблон, скопировав /PATH/TO/grappelli/templates/admin/edit_inline/stacked.html в /PATH/TO/YOURMOD/templates/admin/edit_inline/
  2. В settings.py вашего сайта убедитесь, что YOURMOD выше grappelli в INSTALLED_APPS. В противном случае Django продолжит использовать версию шаблона Grappelli.

код

Теперь вам просто нужно внести два изменения в вашу копию stacked.html. Найдите блок javascript, который начинается:

$("#{{ inline_admin_formset.formset.prefix }}-group").grp_inline({

... и внесите следующие изменения в этот блок:

  1. Добавьте функцию onBeforeAdded следующим образом (или измените существующую функцию, если она существует, но у меня ее нет):

        onBeforeAdded:function(form) {
            // New inlines start as a hidden template with class grp-empty-form.
            // This contains a textarea, which TinyMCE converts correctly, but
            // something about the transformation from template to visible 
            // form breaks TinyMCE, so we need to remove it from the template and 
            // then re-add it after the transformation. 
            // c.f. /5742242/django-grappelli-tabular-inline-dobavit-novuy-stroku-tekstovoe-pole-tinymce-nedostupno-dlya-redaktirovaniya
            if (tinyMCE != undefined) {
                django.jQuery('.grp-empty-form').find('textarea').each(function() { 
                    var tid = django.jQuery(this).attr("id");
                    tinyMCE.execCommand("mceRemoveControl",false,tid); 
                });
            }
        },
    
  2. Добавьте следующее к функции onAfterAdded (у вас уже должна быть одна, поэтому обязательно измените существующую, а не определяйте новую!):

            if (tinyMCE != undefined) {
              // re-initialise tinyMCE instances
              deselector = tinyMCE.settings.editor_deselector;
              django.jQuery(form).find('textarea:not(.'+deselector+')').each(function(k,v) {
                var tid = django.jQuery(this).attr('id');
                tinyMCE.execCommand('mceAddControl', false, tid);
              });
            }
            // This line is optional. It just ensures that the new inline appears
            // un-collapsed, even if inlines are collapsed by default
            django.jQuery(form).removeClass("grp-closed").addClass("grp-open");
    

Вот и все!

EDIT Добавлен деселектор в onAfterLoad - гарантирует, что вы все еще можете определить класс деселекторов в конфигурационном файле tinymce, и inline будет соответствовать этому.

4 голосов
/ 16 октября 2011

У меня не было времени, чтобы разобраться с этим более подробно, поэтому я почти уверен, что есть лучшее решение, но мне кажется, что оно работает (протестировано с django-grappelli 2.3.5 и django-tinymce 1.5.1a2 .

Я предполагаю, что вы используете составные строки.

Вы должны переопределить шаблон из grappelli, templates/admin/edit_inline/stacked.html. Внутри цикла for, повторяющегося по inline_admin_formset|formsetsort:sortable_field_name, сразу после вложенного цикла цикла, повторяющегося по inline_admin_form, добавьте этот фрагмент:

{% if forloop.last %}
  <script type="text/javascript">
    if (tinyMCE != undefined) {
      django.jQuery('textarea', '.empty-form').each(function() {
        tinyMCE.execCommand('mceRemoveControl', false, django.jQuery(this).attr('id'));
      });
    }
  </script>
{% endif %}

он должен отключить элементы управления tinyMCE для текстовой областиэлементы в скрытой «пустой форме», инициализированные встроенным javascript, визуализированным для виджета (ей) tinyMCE.

где-то около строки 133 в исходном шаблоне грапелли вы увидите вызов grp_inline().Добавьте / измените аргументы:

$("#{{ inline_admin_formset.formset.prefix }}-group").grp_inline({
  prefix: "{{ inline_admin_formset.formset.prefix }}",
  onBeforeRemoved: function(f) {
    if (tinyMCE != undefined) {
      // make sure tinyMCE instances in empty-form are inactive
      django.jQuery('textarea', '.empty-form').each(function() {
        tinyMCE.execCommand('mceRemoveControl', false, django.jQuery(this).attr('id'));
      });
    }
  },
  [...]
  onAfterAdded: function(form) {
    if (tinyMCE != undefined) {
      // re-initialise tinyMCE instances
      $('textarea', form).each(function(k,v) {
        var tid = $(this).attr('id');
        tinyMCE.execCommand('mceRemoveControl', false, tid);
        tinyMCE.execCommand('mceAddControl', false, tid);
      });
      // make sure tinyMCE instances in empty-form are inactive
      django.jQuery('textarea', '.empty-form').each(function() {
        tinyMCE.execCommand('mceRemoveControl', false, django.jQuery(this).attr('id'));
      });
    }
    [...]
  }
  [...]

Если вы используете сортируемые файлы, вы также хотели бы отключить элементы управления tinyMCE для текстовых областей перетаскиваемой строки. Найдите инициализацию sortable() и измените 'start'обратный вызов:

start: function(evt, ui) {
  ui.placeholder.height(ui.item.height() + 12);
  if (tinyMCE != undefined) {
    // make sure tinyMCE instances in empty-form are inactive
    $('textarea', ui.item).each(function(k,v) {
      var tid = $(this).attr('id');
      tinyMCE.execCommand('mceRemoveControl', false, tid);
    });
  }
},
[...]

Это должно дать общее представление о том, как обойти эту надоедливую проблему ...

...