Skip to main content
 首页 » 编程设计

python之让 CKEditor 与 Flask Admin 一起工作

2025年05月04日14bonelee

我正在尝试将 Flask Admin 文本框变成 CKEdit 框,如此处所述。但是,当我运行它并转到现有的管理字段时,它没有显示对文本框的任何更改,当我运行它并转到创建的 TestAdmin 字段以演示我收到此错误时:

OperationalError: (OperationalError) 没有这样的表:test u'SELECT count(?) AS count_1\nFROM test' ('*',)

连同一堆其他追溯消息。

我已将我的初始化脚本更改为:

import os 
from flask import Flask 
from flask.ext.sqlalchemy import SQLAlchemy 
from flask.ext.login import LoginManager 
from flask.ext.openid import OpenID 
from flask.ext.mail import Mail 
from config import basedir, ADMINS, MAIL_SERVER, MAIL_PORT, MAIL_USERNAME, MAIL_PASSWORD 
from momentjs import momentjs 
from flask.ext.babel import Babel 
from flask.ext import admin 
from flask_admin.contrib.sqla import ModelView 
from wtforms import TextAreaField 
from wtforms.widgets import TextArea 
 
app = Flask(__name__) 
 
app.config.from_object('config') 
db = SQLAlchemy(app) 
lm = LoginManager() 
lm.init_app(app) 
lm.login_view = 'login' 
oid = OpenID(app, os.path.join(basedir, 'tmp')) 
mail = Mail(app) 
babel = Babel(app) 
 
from app import views, models 
 
 
### 
class CKTextAreaWidget(TextArea): 
    def __call__(self, field, **kwargs): 
        if kwargs.get('class'): 
            kwargs['class'] += " ckeditor" 
        else: 
            kwargs.setdefault('class', 'ckeditor') 
        return super(CKTextAreaWidget, self).__call__(field, **kwargs) 
 
class CKTextAreaField(TextAreaField): 
    widget = CKTextAreaWidget() 
 
 
class Test(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    text = db.Column(db.UnicodeText) 
 
 
class TestAdmin(ModelView): 
    form_overrides = dict(text=CKTextAreaField) 
 
    create_template = 'edit.html' 
    edit_template = 'edit.html' 
 
admin = admin.Admin(app, name = 'PetroTools', template_mode = 'bootstrap3') 
admin.add_view(ModelView(models.Report, db.session)) 
admin.add_view(ModelView(models.Well, db.session)) 
admin.add_view(ModelView(models.Field, db.session)) 
admin.add_view(ModelView(models.Section, db.session)) 
admin.add_view(TestAdmin(Test, db.session)) 
 
if not app.debug: 
    import logging 
    from logging.handlers import SMTPHandler 
    credentials = None 
    if MAIL_USERNAME or MAIL_PASSWORD: 
        credentials = (MAIL_USERNAME, MAIL_PASSWORD) 
    mail_handler = SMTPHandler((MAIL_SERVER, MAIL_PORT), 'no-reply@' + MAIL_SERVER, ADMINS, 'microblog failure', credentials) 
    mail_handler.setLevel(logging.ERROR) 
    app.logger.addHandler(mail_handler) 
 
if not app.debug: 
    import logging 
    from logging.handlers import RotatingFileHandler 
    file_handler = RotatingFileHandler('tmp/microblog.log', 'a', 1 * 1024 * 1024, 10) 
    file_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]')) 
    app.logger.setLevel(logging.INFO) 
    file_handler.setLevel(logging.INFO) 
    app.logger.addHandler(file_handler) 
    app.logger.info('microblog startup') 
 
app.jinja_env.globals['momentjs'] = momentjs 

并且我已将 edit.html 文件放入我的 app/templates 文件夹中。

我对它为什么不起作用的最佳猜测是,也许我不应该将 edit.html 与其他东西一起放入模板文件夹中,而是放在 flask 管理模板文件夹中?但是那个文件夹在哪里?我有一个吗?在 edit.html 它说:

{% extends 'admin/model/edit.html' %}

但是我没有那个目录。这就是搞砸的原因吗?

我想我可能正在做一些非常愚蠢的事情,因为我不了解这件事究竟是如何尝试改变 ckeditor 模板的。谁能帮忙?

非常感谢, 亚历克斯

编辑:这里是 edit.html 文件中的所有内容。我没有从 github 编辑版本,我把它放在文件夹 /app/templates/ 中。

{% extends 'admin/model/edit.html' %} 
 
{% block tail %} 
    {{ super() }} 
    <script src="http://cdnjs.cloudflare.com/ajax/libs/ckeditor/4.0.1/ckeditor.js"></script> 
{% endblock %} 

最终编辑: 在 Cunningham 先生的帮助下,我的最终版本是这样的:

import os 
from flask import Flask 
from flask.ext.sqlalchemy import SQLAlchemy 
from flask.ext.login import LoginManager 
from flask.ext.openid import OpenID 
from flask.ext.mail import Mail 
from config import basedir, ADMINS, MAIL_SERVER, MAIL_PORT, MAIL_USERNAME, MAIL_PASSWORD 
from momentjs import momentjs 
from flask.ext.babel import Babel 
 
### 
from flask.ext import admin 
from flask_admin.contrib.sqla import ModelView 
from wtforms import TextAreaField 
from wtforms.widgets import TextArea 
### 
 
app = Flask(__name__) 
 
app.config.from_object('config') 
db = SQLAlchemy(app) 
lm = LoginManager() 
lm.init_app(app) 
lm.login_view = 'login' 
oid = OpenID(app, os.path.join(basedir, 'tmp')) 
mail = Mail(app) 
babel = Babel(app) 
 
from app import views, models 
 
 
### 
class CKTextAreaWidget(TextArea): 
    def __call__(self, field, **kwargs): 
        if kwargs.get('class'): 
            kwargs['class'] += " ckeditor" 
        else: 
            kwargs.setdefault('class', 'ckeditor') 
        return super(CKTextAreaWidget, self).__call__(field, **kwargs) 
 
class CKTextAreaField(TextAreaField): 
    widget = CKTextAreaWidget() 
 
class TestAdmin(ModelView): 
    form_overrides = dict(text=CKTextAreaField) 
 
    create_template = 'edit.html' 
    edit_template = 'edit.html' 
 
 
###ADMIN### 
admin = admin.Admin(app, name = 'PetroTools', template_mode = 'bootstrap3') 
admin.add_view(TestAdmin(models.Report, db.session)) 
admin.add_view(TestAdmin(models.Well, db.session)) 
admin.add_view(TestAdmin(models.Field, db.session)) 
admin.add_view(TestAdmin(models.Section, db.session)) 
########### 
 
if not app.debug: 
    import logging 
    from logging.handlers import SMTPHandler 
    credentials = None 
    if MAIL_USERNAME or MAIL_PASSWORD: 
        credentials = (MAIL_USERNAME, MAIL_PASSWORD) 
    mail_handler = SMTPHandler((MAIL_SERVER, MAIL_PORT), 'no-reply@' + MAIL_SERVER, ADMINS, 'microblog failure', credentials) 
    mail_handler.setLevel(logging.ERROR) 
    app.logger.addHandler(mail_handler) 
 
if not app.debug: 
    import logging 
    from logging.handlers import RotatingFileHandler 
    file_handler = RotatingFileHandler('tmp/microblog.log', 'a', 1 * 1024 * 1024, 10) 
    file_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]')) 
    app.logger.setLevel(logging.INFO) 
    file_handler.setLevel(logging.INFO) 
    app.logger.addHandler(file_handler) 
    app.logger.info('microblog startup') 
 
app.jinja_env.globals['momentjs'] = momentjs 

起初它仍然没有在管理中将文本字段显示为 ckedit 字段。我通过删除所有表并重新创建它们以及使用 Miguel Grinberg 的 flask 教程中的 db_migrate.py 脚本来让它工作。我还将 models.py 文件中的文本字段从 Text 重命名为 text,不确定是否有任何效果。

请您参考如下方法:

您可以使用 Flask-CKEditor .它提供了一个 CKEditorField,这正是您所需要的。我们需要先安装它:

$ pip install flask-ckeditor 

然后在你的代码中:

from flask import Flask 
from flask_sqlalchemy import SQLAlchemy 
from flask_admin import Admin 
from flask_admin.contrib.sqla import ModelView 
from flask_ckeditor import CKEditor, CKEditorField  # Step 1 
 
app = Flask(__name__) 
app.config['SECRET_KEY'] = 'dev' 
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' 
 
db = SQLAlchemy(app) 
ckeditor = CKEditor(app)  # Step 2 
 
class Post(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    title = db.Column(db.String(120)) 
    text = db.Column(db.Text) 
 
 
# Step 3 
class PostAdmin(ModelView): 
    form_overrides = dict(text=CKEditorField) 
    create_template = 'edit.html' 
    edit_template = 'edit.html' 
 
admin = Admin(app, name='Flask-CKEditor demo') 
admin.add_view(PostAdmin(Post, db.session)) 
 
if __name__ == '__main__': 
    app.run(debug=True) 

在您的模板中 (templates/edit.html):

<!-- Step 4 --> 
{% extends 'admin/model/edit.html' %} 
 
{% block tail %} 
    {{ super() }} 
    {{ ckeditor.load() }} 
    {#  
    If you have set the configuration variables more than CKEDITOR_SERVE_LOCAL and CKEDITOR_PKG_TYPE,  
    or you need to config the CKEditor textarea, use the line below to register the configuration. 
    The name value should be the name of the CKEditor form field. 
    #} 
    {{ ckeditor.config(name='text') }} 
{% endblock %} 

在 GitHub 上获取此演示应用程序.