flask-admin 多个数据库的不同视图

问题描述 投票:0回答:1

我有两个不同的数据库。它们是:股票和商品。每个数据库有两个表如下:

Stock: User_trade_stock, stock_prices
Commodity: User_trade_commodity, commodity_prices

我尝试构建一个 Web 应用程序来使用 Flask 处理两个数据库。当我按如下方式对它们应用 flask-admin 时

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 flask-sqlalchemy flask-admin
1个回答
2
投票

有几个问题。

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, db.session, category='Commodity', name='Test', endpoint='commodity-test'))

要获取视图的 url,您可以使用以下代码:

url_for('stock-test.index')
url_for('stock-test.edit')
url_for('commodity-test.index')
url_for('commodity-test.edit')

其次,如果你想使用Flask-Sqlalchemy的bind功能,你应该在表模型上使用

__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
。注意我使用了混合类
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, template_mode="bootstrap3")
admin.add_view(TestView(StockTest, db.session, category='Stock', name='Test', endpoint='stock-test'))
admin.add_view(TestView(CommodityTest, db.session, category='Commodity', name='Test', endpoint='commodity-test'))


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


if __name__ == '__main__':
    app.run()
© www.soinside.com 2019 - 2024. All rights reserved.