【问题标题】:Preserve existing tables in database when running Flask-Migrate运行 Flask-Migrate 时保留数据库中的现有表
【发布时间】:2016-08-20 18:45:39
【问题描述】:

我有一个包含现有表的数据库。我的代码有一个User 模型。我使用 Flask-Migrate 生成了一个修订版并运行它,它在创建用户表时删除了我现有的表。如何在不删除现有表的情况下运行迁移?

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'my_data'

db = SQLAlchemy(app)
migrate = Migrate(app, db)

manager = Manager(app)
manager.add_command('db', MigrateCommand)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128))

if __name__ == '__main__':
    manager.run()

【问题讨论】:

    标签: python flask alembic


    【解决方案1】:

    如果您的数据库中有现有的表,并且它们在您的代码中没有相应的模型,Alembic (Flask-Migrate) 只知道您的数据库和您的代码之间存在差异。它无法知道(默认情况下)您打算保持这些表不变。

    include_object 函数传递给环境以影响Alembic 将为其生成命令的数据库对象。以下示例跳过列出的表名,但允许其他所有内容。

    def include_object(object, name, type_, reflected, compare_to):
        if type_ == 'table' and name in ('table', 'names', 'to', 'skip'):
            return False
    
        return True
    
    # in env.py
    context.configure(
        # ...
        include_object=include_object
    )
    

    【讨论】:

      【解决方案2】:

      这个问题还有另一种解决方案,它是这样的:

      Alembic 在 target_metadata 参数中查找表,该参数也接受对象列表,因此我们可以从 celery 传递模型。

      我们需要做的就是改变:

      文件 - env.py
      来自

      target_metadata = current_app.extensions["migrate"].db.metadata
      

      from celery_sqlalchemy_scheduler.models import ModelBase
      
      ...
      
      target_metadata = [current_app.extensions["migrate"].db.metadata, ModelBase.metadata]
      

      【讨论】:

        【解决方案3】:

        文件 - 迁移/env.py

        def include_object(object, name, type_, reflected, compare_to):
            _list_preserve_tables = []
            if (
                type_ == "table" and name in _list_preserve_tables
            ):
                return False
            else:
                return True
        
        def run_migrations_offline():
            context.configure(
                url=url,
                target_metadata=target_metadata,
                include_object=include_object,
                literal_binds=True,
                dialect_opts={"paramstyle": "named"},
            )
        
            with context.begin_transaction():
                context.run_migrations()
        

        【讨论】:

        • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
        • A code-only answer is not high quality。虽然此代码可能很有用,但您可以通过说明其工作原理、工作方式、何时应该使用以及它的局限性来改进它。请edit您的回答包括解释和相关文档的链接。
        猜你喜欢
        • 1970-01-01
        • 2017-11-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多