未捕获的引用错误:在 CKEditor 中使用自定义构建时未定义 ClassicEditor

问题描述 投票:0回答:1

我正在构建一个 Flask 博客应用程序并尝试将

CKEditor
集成到模板中。首先,我尝试使用
CDN
来实现它,效果很好。然后我使用 CKEditor 5 Online Builder 构建了一个自定义构建。我下载了 zip 文件,将其解压并将其放入 Flask 项目目录中的静态文件夹中。我将之前链接到
src
的脚本
CDN
更改为我的自定义 CKEditor 版本。执行此操作后,创建新帖子的页面工作正常,并且正确显示 ckeditor 文本区域。但是更新现有帖子的页面显示错误
Uncaught ReferenceError: ClassicEditor is not defined

我的文件夹结构:

>flask_blog_1
    >main
        >__init__.py
        >routes.py
    >posts
        >__init__.py
        >forms.py
        >routes.py
    >static
        >ckeditor //Custom CKEditor5 Build
        >profile_pics
        >main.css
    >templates
        >...
        >create_post.html
        >layout.html
        >...
    >users
        >__init__.py
        >forms.py
        >routes.py
        >utils.py
    >__init__.py
    >config.py
    >models.py
    >instance
        >site.db
    >venv
    >.env
    >run.py

下面是我认为是原因的文件的代码。如果需要更多文件的代码,请询问。

posts/routes.py

from flask import Blueprint, render_template, flash, redirect, url_for, request, abort
from flaskblog import db
from flaskblog.posts.forms import PostForm
from flaskblog.models import Post
from flask_login import current_user, login_required

posts = Blueprint("posts", __name__)


@posts.route("/post/new", methods=["GET", "POST"])
@login_required
def new_post():
    form = PostForm()
    if form.validate_on_submit():
        post = Post(
            title=form.title.data,
            content=form.content.data,
            author=current_user,
        )
        db.session.add(post)
        db.session.commit()
        flash("Your post has been created!", "success")
        return redirect(url_for("main.home"))
    return render_template(
        "create_post.html", title="New Post", form=form, legend="New Post"
    )


@posts.route("/post/<int:post_id>")
def post(post_id):
    post = Post.query.get_or_404(post_id)
    return render_template("post.html", title=post.title, post=post)


@posts.route("/post/<int:post_id>/update", methods=["GET", "POST"])
@login_required
def update_post(post_id):
    post = Post.query.get_or_404(post_id)
    if post.author != current_user:
        abort(403)
    form = PostForm()
    if form.validate_on_submit():
        post.title = form.title.data
        post.content = form.content.data
        db.session.commit()
        flash("Your post has been updated.", "success")
        return redirect(url_for("posts.post", post_id=post.id))
    elif request.method == "GET":
        form.title.data = post.title
        form.content.data = post.content
    return render_template(
        "create_post.html", title="Update Post", form=form, legend="Update Post"
    )


@posts.route("/post/<int:post_id>/delete", methods=["POST"])
@login_required
def delete_post(post_id):
    post = Post.query.get_or_404(post_id)
    if post.author != current_user:
        abort(403)
    db.session.delete(post)
    db.session.commit()
    flash("Your post has been deleted.", "success")
    return redirect(url_for("main.home"))

new_post
post
delete_post
路线运行得很好。问题仅在于
update_post
路线,即使它呈现与
create_post.html
路线相同的
new_post
模板。同样,ckeditor 仅在
Uncaught ReferenceError: ClassicEditor is not defined
路线中显示
update_post
错误。 ckeditor 文本区域也不会显示在此路径中。但在
new_post
路线上效果很好。

templates/layout.html

<!DOCTYPE html>
<html>

<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
        integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='main.css') }}">

    {% if title %}
    <title>Flask Blog - {{ title }}</title>
    {% else %}
    <title>Flask Blog</title>
    {% endif %}

    <!-- ...................................ckeditor......................................... -->

    <!-- <script src="https://cdn.ckeditor.com/ckeditor5/39.0.2/classic/ckeditor.js"></script> -->
    <script src="../static/ckeditor/build/ckeditor.js"></script>

    <!-- ...................................ckeditor end......................................... -->

</head>

<body>
    <header class="site-header">
        <nav class="navbar navbar-expand-md navbar-dark bg-steel fixed-top">
            <div class="container">
                <a class="navbar-brand mr-4" href="/">Flask Blog</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggle"
                    aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="collapse navbar-collapse" id="navbarToggle">
                    <div class="navbar-nav mr-auto">
                        <a class="nav-item nav-link" href="{{ url_for('main.home') }}">Home</a>
                        <a class="nav-item nav-link" href="{{ url_for('main.about') }}">About</a>
                    </div>
                    <!-- Navbar Right Side -->
                    <div class="navbar-nav">
                        {% if current_user.is_authenticated %}
                        <a class="nav-item nav-link" href="{{ url_for('posts.new_post') }}">New Post</a>
                        <a class="nav-item nav-link" href="{{ url_for('users.account') }}">{{ current_user.username
                            }}</a>
                        <a class="nav-item nav-link" href="{{ url_for('users.logout') }}">Logout</a>
                        {% else %}
                        <a class="nav-item nav-link" href="{{ url_for('users.login') }}">Login</a>
                        <a class="nav-item nav-link" href="{{ url_for('users.register') }}">Register</a>
                        {% endif %}
                    </div>
                </div>
            </div>
        </nav>
    </header>
    <main role="main" class="container">
        <div class="row">
            <div class="col-md-8">
                {% with messages = get_flashed_messages(with_categories=true) %}
                {% if messages %}
                {% for category, message in messages %}
                <div class="alert alert-{{ category }}">
                    {{ message }}
                </div>
                {% endfor %}
                {% endif %}
                {% endwith %}
                {% block content %}{% endblock %}
            </div>
            <div class="col-md-4">
                <div class="content-section">
                    <h3>Sidebar</h3>
                    <p class='text-muted'>Put some information here.
                    <ul class="list-group">
                        <li class="list-group-item list-group-item-light">Latest Posts</li>
                        <li class="list-group-item list-group-item-light">Announcements</li>
                        <li class="list-group-item list-group-item-light">Calendars</li>
                        <li class="list-group-item list-group-item-light">etc</li>
                    </ul>
                    </p>
                </div>
            </div>
        </div>
    </main>


    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
        integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
        crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
        integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
        crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
        integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
        crossorigin="anonymous"></script>

    <script>
        ClassicEditor
            .create(document.querySelector('#content'))
            .then(editor => {
                editor.model.document.on('change', () => {
                    document.querySelector('#content-hidden').value = editor.getData();
                    console.log(editor.getData());
                })
            })
            .catch(error => {
                console.error(error);
            });
    </script>
</body>

</html>

在上面的代码中,在

</head>
标签的正上方,我注释掉了 CDN 的脚本标签,并为自定义 CKEditor 构建编写了脚本标签。当我注释掉第二个脚本标签并取消注释第一个脚本标签时,更新页面工作得很好。

templates/create_post.html

{% extends "layout.html" %}

{% block content %}
<div class="content-section">
    <form method="POST" action="">
        {{ form.hidden_tag() }}
        <fieldset class="form-group">
            <legend class="border-bottom mb-4">{{ legend }}</legend>
            <div class="form-group">
                {{ form.title.label(class="form-control-label") }}
                {% if form.title.errors %}
                {{ form.title(class="form-control form-control-lg is-invalid") }}
                <div class="invalid-feedback">
                    {% for error in form.title.errors %}
                    <span>{{ error }}</span>
                    {% endfor %}
                </div>
                {% else %}
                {{ form.title(class="form-control form-control-lg") }}
                {% endif %}
            </div>
            <div class="form-group">
                {{ form.content.label(class="form-control-label") }}
                {% if form.content.errors %}
                <!-- {{ form.content(class="form-control form-control-lg is-invalid", id="content") }} -->
                <div name="content" id="content" class="form-control form-control-lg is-invalid">
                    {% if form.content.data %}
                    {{ form.content.data|safe }}
                    {% endif %}
                </div>
                <input type="hidden" name="content" id="content-hidden" />
                <div class="invalid-feedback">
                    {% for error in form.content.errors %}
                    <span>{{ error }}</span>
                    {% endfor %}
                </div>
                {% else %}
                <!-- {{ form.content(class="form-control form-control-lg", id="content") }} -->
                <div name="content" id="content" class="form-control form-control-lg">
                    {% if form.content.data %}
                    {{ form.content.data|safe }}
                    {% endif %}
                </div>
                <input type="hidden" name="content" id="content-hidden" />
                {% endif %}
            </div>
        </fieldset>
        <div class="form-group">
            {{ form.submit(class="btn btn-outline-info") }}
        </div>
    </form>
</div>
{% endblock content %}

这是我第一次尝试使用CKEditor。我不知道为什么它可以与 cdn 一起使用,但不能与自定义构建一起使用。

javascript flask ckeditor5
1个回答
0
投票

如果我再次遇到同样的问题,回答这个问题是为了我自己的参考。

所以基本上,当我尝试创建新帖子时,它从正确的位置加载

ckeditor.js
文件,即
flaskblog1/flaskblog/static/ckeditor/build/ckeditor.js
。但是当我尝试更新现有帖子时,它试图从
ckeditor.js
加载
flaskblog1/flaskblog/posts/static/ckeditor/build/ckeditor.js
文件,但显然没有找到。这就是它给出该错误的原因。我仍然不知道为什么要这么做。

我通过使用 Flask 的

url_for
函数解决了这个问题,该函数也可以在模板中使用,无论如何我应该从一开始就这样做。基本上,我将脚本标记更改为以下内容:
layout.html

<!-- ...................................ckeditor......................................... -->
<script src="{{ url_for('static', filename='ckeditor/build/ckeditor.js') }}"></script>
<!-- ...................................ckeditor end......................................... -->
© www.soinside.com 2019 - 2024. All rights reserved.