Django-TinyMCE与多个表单

2 投票
3 回答
2408 浏览
提问于 2025-04-18 00:47

我正在尝试创建一个单独的HTML页面,上面有多个TinyMCE编辑器。编辑器的数量根据请求而变化,所以我不能一个一个列举出来并单独初始化它们。以下是我的代码:

views.py:

from tinymce.widgets import TinyMCE
class ThreadForm(forms.Form):
    subject = forms.CharField(max_length=300, widget=forms.TextInput(attrs={'size':'100'}))
    body = forms.CharField(widget=TinyMCE())
class MessageForm(forms.Form):
    thread_pk = forms.IntegerField()
    body = forms.CharField(widget=TinyMCE())

urls.py:

urlpatterns = patterns('',
    ...
    url(r'^tinymce/', include('tinymce.urls')),
)

settings.py:

INSTALLED_APPS = (
    ...
    'tinymce',
)
...
TINYMCE_DEFAULT_CONFIG = {
    'selector': 'textarea',
    'theme': 'advanced',
    'width': 600,
    'height': 300,
    'theme_advanced_toolbar_location': 'top',
    'theme_advanced_buttons1': 'bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,bullist,numlist,|,outdent,indent,hr,|,undo,redo',
    'theme_advanced_buttons2': 'cut,copy,paste,pastetext,pasteword,|,search,replace,|,link,unlink,charmap,|,visualaid,table,|,blockquote,sub,sup,|,preview,code,emotions,image',
    'theme_advanced_buttons3': '',
    'plugins': 'paste,table,spellchecker,searchreplace,emotions',
    'theme_advanced_resizing': True,
}

member_forums.html:

...
{% block headers %}
{{ thread_form.media }}
{% endblock %}
...
<table id="new_thread_table">
    {{ thread_form.as_table }}
</table>
...
{% for message_form in message_forms %}
    <table class="new_message_table">
        {{ message_form.as_table }}
    </table>
    ...
{% endfor %}

在模板中有一个ThreadForm和多个MessageForms。

当我在HTML中注释掉MessageForms时,ThreadForm似乎可以正常工作,但当我取消注释时,ThreadForm加载了一个TinyMCE的界面,但这个界面不更新(添加文本后,撤销按钮不会变为可用状态,尽管它实际上是可用的),而且当我提交表单时,表单的主体内容缺失,导致form.is_valid失败。

我在模板头部只放了{{ thread_form.media }},而MessageForms没有任何内容。循环遍历:

{% for message_form in message_forms %}
    {{ message_form.media }}
{% endfor %}

也没有任何效果。

经过一些研究,似乎在加载MessageForms时,TinyMCE被初始化了太多次,这导致在提交表单时数据丢失(在这个问题的顶部答案中有编辑:TinyMCE与Django:“这个字段是必填的”

我不知道该怎么解决这个问题。任何帮助或建议都将不胜感激。

3 个回答

0

下面的解决方案对我有效。显然,TinyCME的默认JavaScript代码有些问题。

根据你当前的django和tinycme-django设置,你只需要添加一个JavaScript函数来覆盖默认的tinycme脚本。

找到一个在你的HTML页面上加载的.js文件,然后添加下面的函数:

(function ($) {
    function tinymce4_init(selector) {
        var tinymce4_config = { setup: function (editor) { editor.on('change', function () { editor.save(); }); }, "language": "en", "directionality": "ltr", "cleanup_on_startup": true, "custom_undo_redo_levels": 20, "selector": "textarea.tinymce4-editor", "theme": "modern", "plugins": "\n            textcolor save link image media preview codesample contextmenu\n            table code lists fullscreen  insertdatetime  nonbreaking\n            contextmenu directionality searchreplace wordcount visualblocks\n            visualchars code fullscreen autolink lists  charmap print  hr\n            anchor pagebreak\n            ", "toolbar1": "\n            fullscreen preview bold italic underline | fontselect,\n            fontsizeselect  | forecolor backcolor | alignleft alignright |\n            aligncenter alignjustify | indent outdent | bullist numlist table |\n            | link image media | codesample |\n            ", "toolbar2": "\n            visualblocks visualchars |\n            charmap hr pagebreak nonbreaking anchor |  code |\n            ", "contextmenu": "formats | link image", "menubar": true, "statusbar": true }; if (typeof selector != 'undefined') { tinymce4_config['selector'] = selector; }
        tinymce.init(tinymce4_config);
    }
    tinymce4_init();
})();

在上面的代码中,把"selector": "textarea.tinymce4-editor"改成你自己使用的类名、ID或标签名。这是一个包含所有插件等的完整代码片段。

如果你想要一个简化版本,可以使用:

 tinyMCE.init({
     selector: "#id_blog-content",
     theme: "modern"
 });

这里的选择器指的是你表单的ID、类名或标签名。

@Nagra:为了在同一个HTML页面上为不同的表单使用唯一的ID,你可以为你的表单使用前缀。这样,你表单的每个字段都会得到一个唯一的ID,格式是:
id_{prefix}-{field name}

我为每个表单和选择器都设置了唯一的ID:textarea。不过这并没有解决问题。

1

我把Django-TinyMCE去掉了,开始使用TinyMCE 4.0.21。现在运行得非常顺利。

views.py:

...
class ThreadForm(forms.Form):
    subject = forms.CharField(max_length=300, widget=forms.TextInput(attrs={'size':'100'}))
    body = forms.CharField(widget=forms.Textarea(attrs={'class':'thread'}))
...

member_forums.html:

...
{% block headers %}
<script type="text/javascript" src="{% static 'tinymce/tinymce.min.js' %}"></script>
<script type="text/javascript" src="{% static 'tinymce/threads.js' %}"></script>
{% endblock %}

{% block content %}
    ...
    <form id="new_thread_form" method="post" action="">
        {% csrf_token %}
        <table id="new_thread_table">
            {{ thread_form.as_table }}
        </table>
    </form>
    ...
    <form class="new_message_form" method="post" action="">
    {% csrf_token %}
    {% for message_form in message_forms %}
        {{ message_form.thread_pk }}
        <textarea class="message" name="body"></textarea>
    {% endfor %}
    ...
{% endblock %}

threads.js:

tinyMCE.init({
    selector: "textarea.thread",
    theme: "modern",
    ...
});

tinyMCE.init({
    selector: "textarea.message",
    theme: "modern",
    ...
});
0

TinyMCE 是一个用来让文本框变得更好用的工具,它通过 id 来确定哪个文本框需要被转换成 TinyMCE 编辑器。在 HTML 中,id 是应该是唯一的,也就是说每个 id 不能重复。因为我的两个文本框都叫 body,所以 Django 的表单在生成 HTML 时给它们分配了相同的 id。当 TinyMCE 尝试把编辑器应用到这个 id 时,就会失败,因为它遇到了第二个同样的 id。

类似的问题可以参考这个链接:

当加载两个文本框时,TinyMCE 不工作

我把 MessageForm.body 改成了 MessageForm.body1,这样 ThreadForm 的 TinyMCE 就正常工作了。现在我需要逐个修改每个 MessageForm 的 id,但我觉得应该有更好的解决办法。TinyMCE 应该能处理所有的文本框,也许干脆不使用 id 更好?

撰写回答