让CKEditor与Flask Admin一起使用

时间:2016-01-24 01:56:46

标签: python flask ckeditor flask-admin

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

OperationalError: (OperationalError) no such table: test u'SELECT count(?) AS count_1 \nFROM test' ('*',)

还有一堆其他追溯消息。

我已将init脚本更改为:

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放入模板文件夹中与其他东西,但在烧瓶管理模板文件夹中?但那个文件夹在哪里?我有一个吗?在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 %}

最终修改: 在坎宁安先生的帮助下,我的最终版本有效,看起来像这样:

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

首先,它仍然没有在admin中将文本字段显示为ckedit字段。我通过删除所有表并重新创建它们,并使用Miguel Grinberg的烧瓶教程中的db_migrate.py脚本来实现它。我还将models.py文件中的文本字段从Text重命名为text,不确定是否有效。

2 个答案:

答案 0 :(得分:2)

这是一个使用内存中SQLite的简单工作示例。只有两个文件,即烧瓶应用程序和编辑Jinja2 html模板。

使用的库版本是Flask 0.10.1,Flask-SQLAlchemy 2.1和Flask-Admin 1.4。

根文件夹中的烧瓶应用flask-ckeditor.py

from flask import Flask
from flask.ext.admin import Admin
from flask.ext.admin.contrib.sqla import ModelView
from flask.ext.admin.menu import MenuLink
from flask.ext.sqlalchemy import SQLAlchemy
from wtforms.widgets import TextArea, TextInput
from wtforms.fields import TextAreaField

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
app.config['SQLALCHEMY_ECHO'] = True
app.config['DEBUG'] = True
app.config['SECRET_KEY'] = 'super-secret'

db = SQLAlchemy(app)


class Test(db.Model):
    __tablename__ = 'tests'
    id = db.Column(db.Integer, primary_key=True)
    text = db.Column(db.UnicodeText)


class CKEditorWidget(TextArea):
    def __call__(self, field, **kwargs):
        if kwargs.get('class'):
            kwargs['class'] += " ckeditor"
        else:
            kwargs.setdefault('class', 'ckeditor')
        return super(CKEditorWidget, self).__call__(field, **kwargs)


class CKEditorField(TextAreaField):
    widget = CKEditorWidget()


class TestAdminView(ModelView):
    form_overrides = dict(text=CKEditorField)
    can_view_details = True
    create_template = 'edit.html'
    edit_template = 'edit.html'


@app.route('/')
def index():
    return '<a href="/admin/">Click me to get to Admin!</a>'

# Create admin
admin = Admin(app, name='Admin')
admin.add_view(TestAdminView(model=Test, session=db.session, category='Tables', name='Test'))
admin.add_link(MenuLink(name='Public Website', category='', url='/'))


def build_db():

    tests = [
        {
            'text': "<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut</p>"
        },
        {
            'text': "<p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque<p>"
        },
        {
            'text': "<p>At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium</p>"
        }
    ]

    db.drop_all()
    db.create_all()

    for test in tests:
        test_db = Test(**test)
        db.session.add(test_db)
    db.session.commit()


@app.before_first_request
def create_user():
    build_db()

if __name__ == '__main__':
    app.run(debug=True)

Jinja2 html模板文件templates/edit.html

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

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

答案 1 :(得分:2)

您可以使用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() }}
{% endblock %}

GitHub上获取此演示应用程序。