Подтвердить что ты не робот

Django Grappelli Tabular Inline добавить новую строку Текстовое поле TinyMCE не редактируется

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

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

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

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

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

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

http://django-grappelli.readthedocs.org/en/latest/customization.html#using-tinymce

Я замечаю:

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

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

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

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

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

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

4b9b3361

Ответ 1

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

Настройка

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

код

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

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

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

  • Добавьте функцию 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. http://stackoverflow.com/questions/5738173/
            if (tinyMCE != undefined) {
                django.jQuery('.grp-empty-form').find('textarea').each(function() { 
                    var tid = django.jQuery(this).attr("id");
                    tinyMCE.execCommand("mceRemoveControl",false,tid); 
                });
            }
        },
    
  • Добавьте в функцию 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");
    

Что это!

ИЗМЕНИТЬ Добавлен деселектор в onAfterLoad - гарантирует, что вы все еще можете определить класс deselector в файле конфигурации tinymce, а встраиваемые строки будут соответствовать этому.

Ответ 2

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

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

Вы должны переопределить шаблон из grappelli, templates/admin/edit_inline/stacked.html. Внутри цикла for-loop, проходящего через inline_admin_formset|formsetsort:sortable_field_name, сразу после итерации вложенного цикла for 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 для элементов textarea в скрытой "пустой форме", инициализированной встроенным javascript, отображаемым для виджета (ов) tinyMCE.

где-то вокруг строки 133 в исходном шаблоне grappelli вы увидите обращение 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);
    });
  }
},
[...]

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