我正在尝试创建Admin-user可更改的下拉框,然后将在另一个模型中使用它来跟踪事务。 db.relationship方法不能很好地工作,因为验证列表几乎每天都会更改。想想一个交付跟踪应用程序(类DeliveryLog是我存储每个交付的地方,类驱动程序是我存储驱动程序名称的地方,类产品是我存储交付的地方)。
进口和型号:
import os
from flask import Flask, url_for, redirect, render_template, request, abort
from flask_sqlalchemy import SQLAlchemy
from flask_security import Security, SQLAlchemyUserDatastore, UserMixin, RoleMixin, login_required, current_user
import flask_admin
from flask_admin.contrib import sqla
import sys
# Create Flask application
app = Flask(__name__)
app.config.from_pyfile('config.py')
db = SQLAlchemy(app)
# Define models
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))
def __str__(self):
return self.name
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(255), unique=True)
password = db.Column(db.String(255))
active = db.Column(db.Boolean())
confirmed_at = db.Column(db.DateTime())
roles = db.relationship('Role', secondary=roles_users,
backref=db.backref('users', lazy='dynamic'))
def __str__(self):
return self.email
# Setup Flask-Security
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore)
class Driver(db.Model):
id = db.Column(db.Integer, primary_key=True)
driver = db.Column(db.String(255), unique=True)
def __str__(self):
return self.driver
def __repr__(self):
return self.driver
class Product(db.Model):
id = db.Column(db.Integer, primary_key=True)
product = db.Column(db.String(255), unique=True)
def __str__(self):
return self.product
def __repr__(self):
return self.product
class DeliveryLog(db.Model):
id = db.Column(db.Integer, primary_key=True)
date = db.Column(db.DATE,index=True)
operator = db.Column(db.String(127))
on_premises = db.Column(db.Boolean())
cargo = db.Column(db.String(127))
def __str__(self):
return self.operator + ' on ' + str(self.date)
观点,安全背景和主要
class MyAdminView(sqla.ModelView):
def is_accessible(self):
if not current_user.is_active or not current_user.is_authenticated:
return False
if current_user.has_role('superuser'):
return True
return False
def _handle_view(self, name, **kwargs):
"""
Override builtin _handle_view in order to redirect users when a view is not accessible.
"""
if not self.is_accessible():
if current_user.is_authenticated:
# permission denied
abort(403)
else:
# login
return redirect(url_for('security.login', next=request.url))
class MyLogView(MyAdminView):
form_extra_fields = {
'cargo': sqla.fields.QuerySelectField(label='Custom Cargo',
query_factory=db.session.query(Product).all)
}
#Product.query.all
#db.session.query(Product).all
@app.route('/')
@login_required
def index():
return render_template('index.html')
# Create admin
admin = flask_admin.Admin(
app,
'Fruit Tracker',
base_template='my_master.html',
template_mode='bootstrap3',
)
# Add model views
admin.add_view(MyAdminView(Role, db.session))
admin.add_view(MyAdminView(User, db.session))
admin.add_view(MyAdminView(Driver, db.session))
admin.add_view(MyAdminView(Product, db.session))
admin.add_view(MyLogView(DeliveryLog, db.session))
# define a context processor for merging flask-admin's template context into the
@security.context_processor
def security_context_processor():
return dict(
admin_base_template=admin.base_template,
admin_view=admin.index_view,
h=flask_admin.helpers,
get_url=url_for
)
if __name__ == '__main__':
db.create_all()
if 'debug' in sys.argv:
app.run(host='0.0.0.0', port=5001, debug=True)
else:
app.run(host='0.0.0.0', port=80)
虽然表单生成正常并且最新值在下拉列表中,但模型中字段的表示对于SQL Alchemy是不正确的,我得到:
sqlalchemy.exc.InterfaceError
sqlalchemy.exc.InterfaceError:(sqlite3.InterfaceError)绑定错误 参数3 - 可能不支持的类型。 [SQL:'INSERT INTO delivery_log(日期,运营商,on_premises,货运)价值(?,?,?, ?)'] [参数:('2016-08-18','Frank',1,kiwi)]
请记住,这是一个简化的示例,可以教会其他人如何在Flask-Admin中进行子类视图,真正的应用程序将有大型表单(20个字段+至少5个下拉框),因此单字段单级覆盖在这里不起作用。我认为这种允许管理员用户改变应用程序行为方式的模式是将应用程序维护卸载到非开发人员的好方法。谢谢
答案 0 :(得分:0)
看起来SQLlite不喜欢你的on_premises
数据类型。尝试转换' 1'到一个真正的Python布尔值,True
。或者仔细检查一下' 1'是真正的int,而不是字符串。