让CKEditor与Flask Admin一起工作 [英] Getting CKEditor to work with Flask Admin

查看:825
本文介绍了让CKEditor与Flask Admin一起工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在试图将Flask Admin文本框放到CKEdit框中,如下所述。但是,当我运行它并转到现有的管理字段时,它不会显示文本框的任何更改,并且当我运行它并转到创建的TestAdmin字段以演示出现此错误时:



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

伴随着一堆其他的追踪信息。



我把init脚本改成了这个:

 导入os $ b $ from烧瓶导入烧瓶
from flask.ext.sqlalchemy导入SQLAlchemy
from flask.ext.login从flask.ext.openid中导入LoginManager
从flask.ext.mail中导入OpenID
从配置中导入Mail
导入basedir,ADMINS,MAIL_SERVER,MAIL_PORT,MAIL_USERNAME, MAIL_PASSWORD
from momentjs从flask.ext.babel导入momentjs
从flask.ext导入Babel
从flask_admin.contrib.sqla导入admin
导入ModelView
从wtforms导入TextAreaFie ld
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)

从应用程序导入视图中,模型


###
class CKTextAreaWidget(TextArea):
def __call __(self,field,** kwargs):
如果kwargs.get('class'):
kwargs ['class'] + =ckeditor
else:
kwargs.setdefault('class','ckeditor')
return super(CKTextAreaWidget,self).__ call __(field,** kwargs)
$ b $ class CKTextAreaField(TextAreaField):$ b $ widget = CKTextAreaWidget()

$ b $ class Test(db.Model):
id = db.Column(db.Integer,primary_key = True)
text = db.Column(db.UnicodeText)

$ b $ 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(Model.Well,db (Model.Field,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))

如果不是app.debug:
从logging.handlers导入日志记录
import SMTPHandler
credentials = None
(MAIL_SERVER,MAIL_PORT),'no-reply @'+ MAIL_SERVER,ADMINS,'microblog failure',凭证)
mail_handler.setLevel(logging.ERROR)
app.logger.addHandler(mail_handler)

如果不是ap p.debug:
从logging.handlers导入日志
导入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模板。任何人都可以帮忙吗?

非常感谢,
Alex



编辑: strong>以下是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先生的帮助下,我的最终版本工作,看起来像这样:

 从烧瓶导入进口os 
烧瓶
from flask.ext.sqlalchemy从flask.ext.login导入SQLAlchemy
从flask.ext.openid导入LoginManager
从flask.ext.mail导入OpenID
import Mail
从配置导入basedir,ADMINS,MAIL_SERVER,MAIL_PORT,MAIL_USERNAME,MAIL_PASSWORD
从momentjs进口momentjs $ b $从flask.ext.babel进口Babel

###
from flask.ext import admin $ b $ from flask_admin.contrib.sqla从wtforms导入ModelView
从wtforms.widgets导入TextAreaField
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):
如果kwargs.get('class'):
kwargs ['class'] + =ckeditor
else:
kwargs.setdefault('class','ckeditor')
return super(CKTextAreaWidget,self).__ call __(field,** kwargs)

class CKTextAreaField(TextAreaField):$ b $ widget = CKTextAreaWidget()
$ b 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(Model.Well,db。会话))
admin.add_view(TestAdmin(models.Field,db.sessio n))
admin.add_view(TestAdmin(models.Section,db.session))
###########

如果不是app.debug :
从logging.handlers导入日志记录
导入SMTPHandler
凭证=无
如果MAIL_USERNAME或MAIL_PASSWORD:
凭证=(MAIL_USERNAME,MAIL_PASSWORD)
mail_handler = SMTPHandler((MAIL_SERVER,MAIL_PORT),'no-reply @'+ MAIL_SERVER,ADMINS,'microblog failure',凭证)
mail_handler.setLevel(logging.ERROR)
app.logger.addHandler(mail_handler)

如果不是app.debug:
从logging.handlers导入日志
导入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的flask教程中的db_migrate.py脚本来实现它。我还将 models.py 文件中的文本字段从 Text 更改为 text ,不知道是否有任何影响。

解决方案

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



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


$ b 根文件夹中的应用程序 flask-ckeditor.py

 从瓶子导入Flask 
从flask.ext.admin导入Admin $ b $从flask.ext.admin.contrib.sqla导入ModelView
from flask.ext.admin.menu导入MenuLink
from flask.ext.sqlalchemy从wtforms.widgets导入SQLAlchemy
从wtforms.fields导入TextArea,TextInput
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)

$ b class CKEditorWidget(TextArea):
def __call __(self,field,* * kwargs):
如果kwargs.get('class'):
kwargs ['class'] + =ckeditor
else:
kwargs.setdefault('class' ,'ckeditor')
return super(CKEditorWidget,self).__ call __(field,** kwargs)

$ b $ class CKEditorField(TextAreaField):$ b $ widget = CKEditorWidget ()

$ b $ 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 />点击我进入管理员< / a>'

#创建管理员
admin =管理员(应用程序,名称='Admin')
admin.add_view(TestAdminView(model = Test,session = db.session,category = ('name ='Test'))
admin.add_link(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>在vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium< / p>


$ b $ db.drop_all()
db.create_all()

在测试中测试:
test_db = Test(** test)
db.session.add(test_db)
db.session.commit()


@ app.before_first_request
def create_user():
build_db()
$ b $ if 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%}


I'm trying to make turn the Flask Admin text box into a CKEdit box, as described here. However, when I run it and go to the existing admin fields it doesn't show any change to the text boxes, and when I run it and go to the TestAdmin field created to demonstrate I get this error:

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

Along with a bunch of other traceback messages.

I have changed my init script to be this:

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

and I've put the edit.html file in my app/templates folder.

My best guess at why it's not working is that maybe I'm not supposed to put edit.html into the templates folder with the other things, but in the flask admin templates folder? But where is that folder? Do I even have one? In edit.html it says:

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

But I don't have that directory. Is that what's screwing it up?

I figure I'm probably doing something pretty stupid due to my lack of understanding of how exactly this thing is trying change the ckeditor template. Can anyone help?

Thanks a lot, Alex

Edit: Here is everything in the edit.html file. I haven't edited the version from github, and I have it in the folder /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 %}

Final Edit: With Mr Cunningham's help, my final version works and looks like this:

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

At first it still wasn't showing text fields as ckedit fields in admin. I got it to work by dropping all the tables and recreating them, and also using db_migrate.py script from Miguel Grinberg's flask tutorial. I also renamed the text field in my models.py file from Text to text, not sure if that had any effect.

解决方案

Here is a simple working example using in-memory SQLite. There are only two files, the flask application and the edit Jinja2 html template.

Library versions used are Flask 0.10.1, Flask-SQLAlchemy 2.1 and Flask-Admin 1.4.

The flask application flask-ckeditor.py in the root folder:

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)

The Jinja2 html template file 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 %}

这篇关于让CKEditor与Flask Admin一起工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆