【问题标题】:Add RTF/Rich Text Editor to CustomUserCreationForm/CustomUserEditForm将 RTF/富文本编辑器添加到 CustomUserCreationForm/CustomUserEditForm
【发布时间】:2026-01-12 21:30:01
【问题描述】:

我尝试按照here 的描述扩展我的自定义User 模型。 这适用于ModelChoiceFieldCharField 等显示的字段。 我现在的目标是添加一个RTF 字段(类似于Page 模型中显示的控件)。我查看了wagtail 的源代码,发现get_rich_text_editor_widget 方法与CharField 结合使用。可悲的是,我收到了 JavaScript 错误:

未捕获的类型错误:无法读取未定义的属性“initEditor”

我现在的猜测是我需要以某种方式包含或修改小部件的挂钩。或者是否足以覆盖模板中的JavaScript 块?现在感觉有点 hacky,我坚持包含所需的JS,这就是我发布问题的原因。也许我错过了一些微不足道的东西。

# ...
from wagtail.admin.rich_text import get_rich_text_editor_widget

class CustomUserEditForm(UserEditForm):
    position = forms.ModelChoiceField(queryset=Position.objects, required=True, label=_('Position'))
    # biography = forms.Textarea()
    biography = forms.CharField(widget=get_rich_text_editor_widget())

更新: 更新我的模板(可能不是正确的方法):

{% block js %}
{{ block.super }}

<script type="text/javascript" src="/static/wagtailadmin/js/draftail.js"></script>

{% endblock js %}

结果:

【问题讨论】:

  • 您也可以将&lt;link href="/static/wagtailadmin/css/panels/draftail.css" type="text/css" media="all" rel="stylesheet"&gt; 添加到{% block extra_css %}。在开发控制台中输入window.draftail.initEditor 会发生什么?您可以使用富文本编辑器将您的 html 与常规页面进行比较并寻找差异。当您执行widget=get_rich_text_editor_widget(name='default', features=['h2']) 时会发生什么?
  • 正确添加CSS 样式RTF 字段。基本功能似乎工作。添加图像/页面/文档会使编辑器崩溃。似乎需要更多相关的JS(例如TypeError: Cannot read property 'imageChooser' of undefined)。在添加 JS 之前,window.draftail 是未定义的。现在它返回函数。通过 args 可以按预期工作。通过模板添加功能可能是一种解决方案,但我找不到所需的所有引用,并希望以更具声明性的方式导入它们。
  • 我认为页面模板 do 具有所有上下文富文本 (Draftail) 需求。我可以想象在其他上下文(如用户模型视图)中使用 Draftail 甚至没有被原始作者考虑。为 Wagtail 提供功能可能是一个不错的选择。但这在短期内对你没有帮助。我认为扣款是最快的。从常规页面加载 all js 并逐个删除脚本,直到您拥有所需的最小集。很脏,但应该可以用 TM。

标签: django django-forms rtf wagtail


【解决方案1】:

我已将我的解决方案写成草稿的问题

https://github.com/springload/draftail/issues/450

我有一个 wagtail 网站,里面有这个很棒的 RichText 编辑器(称为 Draftail),但试图在非 Wagtail 管理页面上使用它让我觉得很脏。我想要一个人们可以写自己的传记领域,我希望博客作者也能够使用它。但要做到这一点,我不得不做一些让我畏缩的事情。

还不错:

{% block extra_css %}
  <link href="{% static 'wagtailadmin/css/panels/draftail.css' %}" type="text/css" media="all" rel="stylesheet">
{% endblock extra_css %}

WTF????为什么我们不只是将网站图标用于粗体之类的东西

    <div data-sprite></div>
    <script>
        function loadIconSprite() {
            var spriteURL = '{% url "wagtailadmin_sprite" %}';
            var revisionKey = 'wagtail:spriteRevision';
            var dataKey = 'wagtail:spriteData';
            var isLocalStorage = 'localStorage' in window && typeof window.localStorage !== 'undefined';

            var insertIt = function (data) {
                var spriteContainer = document.body.querySelector('[data-sprite]');
                spriteContainer.innerHTML = data;
            }

            var insert = function (data) {
                if (document.body) {
                    insertIt(data)
                } else {
                    document.addEventListener('DOMContentLoaded', insertIt.bind(null, data));
                }
            }

            if (isLocalStorage && localStorage.getItem(revisionKey) === spriteURL) {
                var data = localStorage.getItem(dataKey);
                if (data) {
                    insert(data);
                    return true;
                }
            }

            try {
                var request = new XMLHttpRequest();
                request.open('GET', spriteURL, true);
                request.onload = function () {
                    if (request.status >= 200 && request.status < 400) {
                        data = request.responseText;
                        insert(data);
                        if (isLocalStorage) {
                            localStorage.setItem(dataKey, data);
                            localStorage.setItem(revisionKey, spriteURL);
                        }
                    }
                }
                request.send();
            } catch (e) {
                console.error(e);
            }
        }
        loadIconSprite();
    </script>

因为 wagtail cmets.js 不知何故需要 wagtailConfig.ADMIN_API 并且没有 cmets.js,draftail 不会初始化

      <script>
        (function(document, window) {
            window.wagtailConfig = window.wagtailConfig || {};
            wagtailConfig.ADMIN_API = {
                PAGES: '',
                DOCUMENTS: '',
                IMAGES: '',
                {# // Use this to add an extra query string on all API requests. #}
                {# // Example value: '&order=-id' #}
                EXTRA_CHILDREN_PARAMETERS: '',
            };

            {% i18n_enabled as i18n_enabled %}
            {% locales as locales %}
            wagtailConfig.I18N_ENABLED = {% if i18n_enabled %}true{% else %}false{% endif %};
            wagtailConfig.LOCALES = {{ locales|safe }};

            wagtailConfig.STRINGS = {% js_translation_strings %};

            wagtailConfig.ADMIN_URLS = {
                PAGES: ''
            };
        })(document, window);
    </script>
    <script src="{% static 'wagtailadmin/js/vendor/jquery-3.5.1.min.js' %}"></script>
    <!-- <script src="{% static 'wagtailadmin/js/core.js' %}"></script> strangely not needed -->
    <script src="{% static 'wagtailadmin/js/vendor.js' %}"></script>
    <script src="{% static 'wagtailadmin/js/comments.js' %}"></script>
    {{ form.media.js }}

所有这些只是为了让草稿编辑器出现在非 wagtail 管理页面上!

【讨论】:

  • 您好,谢谢您的回答。我对这种方法的问题是,实际使用它进行生产感觉太老套了。感谢您将此作为改进 wagtail 的功能请求发布。让我们看看 gasman 是怎么说的。