【问题标题】:How can I initialize a database table with Flask / SQLalchemy / Alembic?如何使用 Flask / SQLalchemy / Alembic 初始化数据库表?
【发布时间】:2019-06-14 16:04:13
【问题描述】:

我有一个内容相对静态的语言数据库表:

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

class Language(db.Model):
    __tablename__ = 'languages'

    # Fields
    code = db.Column(db.String(2), primary_key=True)
    name = db.Column(db.String(40))
    native = db.Column(db.String(60))
    rtl = db.Column(db.Boolean())  # right to left

data is in a CSV。我想将它插入数据库。我可以用 alembic 做到这一点吗?

我用

初始化所有表(结构,而不是数据)
$ flask db init
$ flask db migrate
$ flask db update

(附带问题:这应该首先在数据库中,还是作为代码中的 CSV?我在 CMS 中使用它来允许用户指定说哪种语言/页面是哪种语言他们创造了。)

我的尝试

提供一个在调用时添加内容的端点:

@app.route('/secret_init_languages')
def db_init_languages():
    from mpu.string import str2bool
    import csv
    path = resource_filename('my_package', 'static/languages.csv')
    nb_languages = 0
    with open(path, 'rt', newline='') as csvfile:
        csvreader = csv.reader(csvfile, delimiter=',')
        next(csvreader, None)  # skip the headers
        for row in csvreader:
            lang = Language(code=row[0],
                            name=row[1],
                            native=row[2],
                            rtl=str2bool(row[3]))
            db.session.add(lang)
            nb_languages += 1
        db.session.commit()
    return 'Added {} languages'.format(nb_languages)

此解决方案的缺点:

  • 我有一个只能调用一次的端点
  • 我可能忘记运行它

【问题讨论】:

  • alembic 主要不是数据迁移工具。您可以使用 flask-migrate 使用正确的表更新数据库,但您需要自己移动数据。 db = SQLAlchemy()class Language(db.Model): 对我来说没有意义,除非你也在使用 flask-sqlalchemy
  • 我认为db = SQLAlchemy()不会在应用程序上注册
  • @roganjosh 是的,我确实使用 flask-sqlalchemy。出于这个原因,我添加了标签。我当然会db.init_app(app)
  • @roganjosh 那么首选的数据迁移工具是什么? (我有一个 MySQL-DB)
  • 嗯,这使我正在输入中途的答案无效。现在我不知道你在问什么

标签: python sqlalchemy flask-sqlalchemy data-migration alembic


【解决方案1】:

不确定您是否已经解决了这个问题,我在使用 Flask 和 SQLAlchemy 使用 csv 初始化数据库表时遇到了类似的问题。以下解决方案对我有用(不使用 alembic):

from main.app import app
from main.db import db
from models.table import TableModel
from pandas import read_csv

db.init_app(app)

@app.before_first_request
def create_tables():
    db.create_all()
    # Check if the existing table contain data, if not then initialize with csv insert
    s = db.session()
    if len(s.query(TableModel).all()) == 0:
        print('No data in the table detected.')
        print('Initialising the table in database.')
        engine = s.get_bind()
        df = read_csv('./table.csv')
        df.to_sql('table',
                  con=engine,
                  if_exists='append',
                  chunksize=1000,
                  index=False)

app.run(port=5000, debug=True)

请注意,上面的代码包含在 run.py 脚本中,该脚本分别从 main.app 和 main.db 模块调用 flask 应用程序对象和 SQLAlchemy 对象(来自 flask-sqlalchemy)。 TableModel 是映射到数据库中所需表的类。我将@app.before_first_request 装饰器与pandas.DataFrame.to_sql 方法一起使用,这样数据库的初始化(包括从csv 插入数据)只会在应用程序最初启动时执行一次。我不确定alembic 是否对您有要求,但pandas 确实对我有用,我希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    • 2021-07-09
    • 2020-09-25
    • 2014-12-02
    • 2020-06-12
    • 2021-01-24
    相关资源
    最近更新 更多