13

我正在为我的项目使用 django Grappelli 皮肤。

我有一个带有表格内联函数的 ModelAdmin。

我使用 extra = 0 来防止在加载页面时自动插入空白行。它工作正常。

现在,当我单击 + 号插入新行时,该行已加载,但 tinymce 文本字段不可编辑。

有谁知道是什么原因以及如何解决这个问题?

阅读文档后:

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

我注意到:

由于隐藏的空表单,使用带有 Inlines 的 TinyMCE 有点棘手。您需要编写一个自定义模板并使用 inline-callbacks 来

onInit:从空表单中删除 TinyMCE 实例。

onAfterAdded:从表单初始化 TinyMCE 实例。

onBeforeRemoved:从表单中删除 TinyMCE 实例。

默认情况下不支持带内联的 TinyMCE。

有这方面的样品吗?我注意到这是我需要更改的 TinyMCE 功能。

4

2 回答 2

14

自从编写了 Almflm 的解决方案以来,Grappelli 使用的一些 CSS 类和 HTML 结构似乎发生了变化。但是,我能够修改 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. 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); 
                });
            }
        },
    
  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");
    

而已!

编辑 将取消选择器添加到onAfterLoad- 确保您仍然可以在 tinymce 配置文件中定义取消选择器类,并且内联将符合此要求。

于 2013-10-29T16:03:06.807 回答
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 %}

它应该禁用对隐藏的“空表单”中的 textarea 元素的 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'));
      });
    }
    [...]
  }
  [...]

如果您使用可排序,您还希望禁用被拖动的内联文本区域上的 tinyMCE 控件。寻找sortable()初始化,并修改“开始”回调:

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);
    });
  }
},
[...]

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

于 2011-10-15T22:05:23.747 回答