Django Grappelli表格内联添加新行TinyMCE文本字段不可编辑

kel*_*fix 12 django tinymce django-admin django-grappelli django-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.

有什么样的吗?我注意到我需要更改它是一个TinyMCE功能.

小智 14

看起来Grappelli使用的一些CSS类和HTML结构自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({
Run Code Online (Sandbox Code Playgroud)

...并在该块内进行以下更改:

  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. 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); 
                });
            }
        },
    
    Run Code Online (Sandbox Code Playgroud)
  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");
    
    Run Code Online (Sandbox Code Playgroud)

而已!

编辑 添加了deselector到onAfterLoad- 确保您仍然可以在tinymce配置文件中定义一个deselector类,并且内联将符合这一点.

  • 对于tinymce 4.x,分别使用mceAddEditor和mceRemoveEditor作为mceAddControl和mceRemoveControl的命令名称instread (2认同)

小智 4

我没有时间更彻底地研究这个问题,所以我很确定有更好的解决方案,但这似乎对我有用(使用django-grappelli 2.3.5django-tinymce 1.5.1a2进行测试。

我假设您正在使用堆叠内联。

您必须覆盖 grappelli 中的模板,templates/admin/edit_inline/stacked.html. 在 for 循环迭代 内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 %}
Run Code Online (Sandbox Code Playgroud)

它应该禁用隐藏“空表单”中文本区域元素的tinyMCE控件,该控件由为tinyMCE小部件呈现的内联javascript初始化。

在原始 grappelli 模板中第 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'));
      });
    }
    [...]
  }
  [...]
Run Code Online (Sandbox Code Playgroud)

如果您使用可排序,您还需要禁用正在拖动的内联文本区域上的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);
    });
  }
},
[...]
Run Code Online (Sandbox Code Playgroud)

这应该给出如何解决这个讨厌的问题的粗略想法......