[英]How do I properly set up flask-admin views with using an application factory?
我正在尝试使用SQLAlchemy针对“用户”和“角色”模型设置flask-admin模型视图 。 而不是我得到的功能管理员视图:
ValueError: Invalid model property name <class 'app.models.Role'>.desc
堆栈跟踪:
Traceback (most recent call last):
File "/Users/dbg/Projects/Python/Current/ziff/flaskbase/manage.py", line 18, in <module>
app = create_app(os.getenv('APP_CONFIG') or 'default')
File "/Users/dbg/Projects/Python/Current/ziff/flaskbase/app/__init__.py", line 49, in create_app
admin.add_view(RoleAdmin(Role, db.session))
File "/usr/local/share/anaconda/envs/flaskbase27/lib/python2.7/site-packages/Flask_Admin-1.0.9-py2.7.egg/flask_admin/contrib/sqla/view.py", line 288, in __init__
menu_icon_value=menu_icon_value)
File "/usr/local/share/anaconda/envs/flaskbase27/lib/python2.7/site-packages/Flask_Admin-1.0.9-py2.7.egg/flask_admin/model/base.py", line 570, in __init__
self._refresh_cache()
File "/usr/local/share/anaconda/envs/flaskbase27/lib/python2.7/site-packages/Flask_Admin-1.0.9-py2.7.egg/flask_admin/model/base.py", line 640, in _refresh_cache
self._refresh_forms_cache()
File "/usr/local/share/anaconda/envs/flaskbase27/lib/python2.7/site-packages/Flask_Admin-1.0.9-py2.7.egg/flask_admin/model/base.py", line 580, in _refresh_forms_cache
self._create_form_class = self.get_create_form()
File "/usr/local/share/anaconda/envs/flaskbase27/lib/python2.7/site-packages/Flask_Admin-1.0.9-py2.7.egg/flask_admin/model/base.py", line 856, in get_create_form
return self.get_form()
File "/usr/local/share/anaconda/envs/flaskbase27/lib/python2.7/site-packages/Flask_Admin-1.0.9-py2.7.egg/flask_admin/model/base.py", line 848, in get_form
return self.scaffold_form()
File "/usr/local/share/anaconda/envs/flaskbase27/lib/python2.7/site-packages/Flask_Admin-1.0.9-py2.7.egg/flask_admin/contrib/sqla/view.py", line 607, in scaffold_form
extra_fields=self.form_extra_fields)
File "/usr/local/share/anaconda/envs/flaskbase27/lib/python2.7/site-packages/Flask_Admin-1.0.9-py2.7.egg/flask_admin/contrib/sqla/form.py", line 427, in get_form
for name, p in properties:
File "/usr/local/share/anaconda/envs/flaskbase27/lib/python2.7/site-packages/Flask_Admin-1.0.9-py2.7.egg/flask_admin/contrib/sqla/form.py", line 422, in <genexpr>
properties = ((x, find(x)) for x in only)
File "/usr/local/share/anaconda/envs/flaskbase27/lib/python2.7/site-packages/Flask_Admin-1.0.9-py2.7.egg/flask_admin/contrib/sqla/form.py", line 419, in find
raise ValueError('Invalid model property name %s.%s' % (model, name))
ValueError: Invalid model property name <class 'app.models.Role'>.desc
我正在使用带有蓝图的烧瓶应用工厂方法。 这是我的应用工厂。
我在__init__.py
文件中尝试在第49行创建视图:
from flask import Flask
from flask.ext.bootstrap import Bootstrap
from flask.ext.mail import Mail
from flask.ext.moment import Moment
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.security import Security
from flask.ext.admin import Admin
from flask_s3 import FlaskS3
from flask.ext.cdn import CDN
from flask.ext.assets import Environment
from flask.ext.assets import PythonLoader as PythonAssetsLoader
from config import config
# app setup
bootstrap = Bootstrap()
mail = Mail()
moment = Moment()
db = SQLAlchemy()
security = Security()
admin = Admin()
s3 = FlaskS3()
cdn = CDN()
assets_env = Environment()
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
app.name = app.config['APP_NAME']
config[config_name].init_app(app)
from .models import user_datastore, User, Role
from .auth.views import RoleAdmin, UserAdmin
bootstrap.init_app(app)
mail.init_app(app)
moment.init_app(app)
db.init_app(app)
security.init_app(app, user_datastore)
admin.init_app(app)
s3.init_app(app)
cdn.init_app(app)
assets_env.init_app(app)
# Here's where I'm trying to create the views
admin.add_view(RoleAdmin(Role, db.session))
admin.add_view(UserAdmin(User, db.session))
from . import assets
assets_loader = PythonAssetsLoader(assets)
for name, bundle in assets_loader.load_bundles().iteritems():
assets_env.register(name, bundle)
# attach asset bundles, routes, and custom error pages here
from main import main as main_blueprint
app.register_blueprint(main_blueprint)
import main.assets as main_assets
assets_loader = PythonAssetsLoader(main_assets)
for name, bundle in assets_loader.load_bundles().iteritems():
assets_env.register(name, bundle)
from auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint)
return app
我的ModelView类:
from flask.ext.admin.contrib.sqla import ModelView
__author__ = 'dbg'
class RoleAdmin(ModelView):
column_display_pk = True
form_columns = ['id', 'desc']
class UserAdmin(ModelView):
column_display_pk = True
form_columns = ['id', 'email', 'active', 'last_login_at', 'login_count', 'roles']
编辑
Models.py
from app import db
from flask.ext.security import UserMixin, RoleMixin, SQLAlchemyUserDatastore
roles_users = db.Table('roles_users',
db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))
class Role(db.Model, RoleMixin):
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(80), unique=True)
description = db.Column(db.String(255))
class User(db.Model, UserMixin):
id = db.Column(db.Integer(), primary_key=True)
email = db.Column(db.String(256), unique=True)
password = db.Column(db.String(36))
active = db.Column(db.Boolean())
confirmed_at = db.Column(db.DateTime())
last_login_at = db.Column(db.DateTime())
current_login_at = db.Column(db.DateTime())
last_login_ip = db.Column(db.String(45))
current_login_ip = db.Column(db.String(45))
login_count = db.Column(db.Integer())
roles = db.relationship('Role', secondary=roles_users,
backref=db.backref('users', lazy='dynamic'))
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
UPDATE
这个善良的灵魂 在这里找到了一个非常有用的写作。 仍然卡住了。 新错误。
Traceback (most recent call last):
File "/Users/dbg/Projects/Python/Current/ziff/flaskbase/manage.py", line 18, in <module>
app = create_app(os.getenv('APP_CONFIG') or 'default')
File "/Users/dbg/Projects/Python/Current/ziff/flaskbase/app/__init__.py", line 83, in create_app
admin.add_view(RoleAdmin(RoleAdmin, db.session))
File "/usr/local/share/anaconda/envs/flaskbase27/lib/python2.7/site-packages/Flask_Admin-1.0.9-py2.7.egg/flask_admin/contrib/sqla/view.py", line 288, in __init__
menu_icon_value=menu_icon_value)
File "/usr/local/share/anaconda/envs/flaskbase27/lib/python2.7/site-packages/Flask_Admin-1.0.9-py2.7.egg/flask_admin/model/base.py", line 570, in __init__
self._refresh_cache()
File "/usr/local/share/anaconda/envs/flaskbase27/lib/python2.7/site-packages/Flask_Admin-1.0.9-py2.7.egg/flask_admin/model/base.py", line 632, in _refresh_cache
self._list_columns = self.get_list_columns()
File "/usr/local/share/anaconda/envs/flaskbase27/lib/python2.7/site-packages/Flask_Admin-1.0.9-py2.7.egg/flask_admin/model/base.py", line 708, in get_list_columns
columns = self.scaffold_list_columns()
File "/usr/local/share/anaconda/envs/flaskbase27/lib/python2.7/site-packages/Flask_Admin-1.0.9-py2.7.egg/flask_admin/contrib/sqla/view.py", line 371, in scaffold_list_columns
for p in self._get_model_iterator():
File "/usr/local/share/anaconda/envs/flaskbase27/lib/python2.7/site-packages/Flask_Admin-1.0.9-py2.7.egg/flask_admin/contrib/sqla/view.py", line 310, in _get_model_iterator
return model._sa_class_manager.mapper.iterate_properties
AttributeError: type object 'RoleAdmin' has no attribute '_sa_class_manager'
嗯,这是旧的,但这是我如何做到的:
# Inside app/auth/__init__.py (auth module includes admin):
#...
from app import db
from flask import Blueprint
from .my_custom_model_views import MyModelView
from ..models import MyModel
#...
auth = Blueprint('auth', __name__)
from . import views
#...
auth.custom_model_views = []
auth.custom_model_views += [MyModelView(MyModel, db.session)]
#...
from . import forms
# Inside app/__init__.py
# ...
admin = Admin(name='Name', ...)
# ...
def create_app(config_name):
# ...
app = Flask(__name__)
# ...
admin.init_app(app)
# And here's the important part
with app.app_context():
from .auth import auth as auth_blueprint
admin.add_views(*auth_blueprint.custom_model_views)
重要的部分是以某种方式存储您想要添加的视图(这里,我只是将它们附加到蓝图),然后添加它们与APP上下文。 否则,一切都变得狂暴(没有应用程序上下文,可能会多次添加相同的模型,导致在应用程序实例化期间出现丑陋的名称冲突错误)。
值得注意的是,您在此处添加的任何视图都将显示在烧瓶管理菜单中,就好像它是模型视图一样,即使它是其他类型的视图。 您可以通过更改视图的is_visible和is_accessible方法来解决此问题。
这是使用蓝图的另一种方式:
# app/__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_admin import Admin
db = SQLAlchemy()
admin = Admin(name='my-app', template_mode='bootstrap3')
def create_app():
app = Flask(__name__)
db.init_app(app)
admin.init_app(app)
# Add the admin panel
from app.admin import bp as admin_bp
app.register_blueprint(admin_bp)
return app
# app/admin/__init__.py
from flask import Blueprint
bp = Blueprint('admin_bp', __name__)
from app.admin import routes
# app/admin/routes.py
from flask_admin.contrib.sqla import ModelView
from app import db, admin
from app.models import City
admin.add_view(ModelView(City, db.session))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.