问题描述
我有两个不同的数据库。它们是:股票和商品。每个数据库有如下两张表:
Stock: User_Trade_stock,stock_prices
commodity: User_Trade_commodity,commodity_prices
我尝试构建一个 Web 应用程序来使用 Flask 处理两个数据库。当我按如下方式对它们应用烧瓶管理时
admin.add_view(UserView(User_Trade_stock,db.session))
admin.add_view(UserView(User_Trade_commodity,db.session))
我给出了以下错误:
Assertion Error: A name collision occurred between blueprints. Blueprints that are created on the fly need unique name.
我尝试将绑定添加到 db.session 如下
admin.add_view(UserView(User_Trade_stock,db.session(bind='stock_bind')))
admin.add_view(UserView(User_Trade_commodity,db.session='commodity_bind')))
我收到以下错误:
scoped session is already present; no new arguments may be specified
任何帮助将不胜感激
解决方法
有几个问题。
Flask-Admin 使用视图的小写类名称作为自动生成的蓝图名称。当您使用 UserView
两次时,您会遇到蓝图名称冲突。为了克服这个问题,您可以在实例化视图时指定一个 endpoint
名称,例如:
admin = Admin(app,template_mode="bootstrap3")
admin.add_view(TestView(StockTest,db.session,category='Stock',name='Test',endpoint='stock-test'))
admin.add_view(TestView(CommodityTest,category='Commodity',endpoint='commodity-test'))
要获取视图的网址,您将使用以下代码:
url_for('stock-test.index')
url_for('stock-test.edit')
url_for('commodity-test.index')
url_for('commodity-test.edit')
其次,如果你想使用 Flask-Sqlalchemy 的 bind feature 你应该使用表模型上的 __bind_key__
属性,例如:
class User(db.Model):
__bind_key__ = 'users'
id = db.Column(db.Integer,primary_key=True)
username = db.Column(db.String(80),unique=True)
这是一个说明这两个概念的单个文件示例。在使用应用程序本身之前,您需要运行 Flask 命令 flask create-databases
和 flask populate-databases
。请注意,我使用了一个 mixin 类 TestMixin
来定义模型列。
import click
from flask import Flask
from flask.cli import with_appcontext
from flask_sqlalchemy import SQLAlchemy
from flask_admin import Admin
from flask_admin.contrib.sqla import ModelView
from faker import Faker
from sqlalchemy import Integer,Column,Text
db = SQLAlchemy()
app = Flask(__name__)
app.config['SECRET_KEY'] = '123456790'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['SQLALCHEMY_BINDS'] = {
'stock': 'sqlite:///stock.db','commodity': 'sqlite:///commodity.db'
}
db.init_app(app)
class TestMixin(object):
id = Column(Integer,primary_key=True)
name = Column(Text(),unique=True,nullable=False)
class StockTest(db.Model,TestMixin):
__bind_key__ = 'stock'
class CommodityTest(db.Model,TestMixin):
__bind_key__ = 'commodity'
@click.command('create-databases')
@with_appcontext
def create_databases():
db.drop_all(bind=['stock','commodity'])
db.create_all(bind=['stock','commodity'])
@click.command('populate-databases')
@with_appcontext
def populate_databases():
_faker = Faker()
db.session.bulk_insert_mappings(StockTest,[{'name': _faker.name()} for _ in range(100)])
db.session.bulk_insert_mappings(CommodityTest,[{'name': _faker.name()} for _ in range(100)])
db.session.commit()
class TestView(ModelView):
pass
app.cli.add_command(create_databases)
app.cli.add_command(populate_databases)
admin = Admin(app,endpoint='commodity-test'))
@app.route('/')
def index():
return '<a href="/admin/">Click me to get to Admin!</a>'
if __name__ == '__main__':
app.run()