Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 创建表后向SQLAlchemy模型添加索引_Python_Indexing_Sqlalchemy - Fatal编程技术网

Python 创建表后向SQLAlchemy模型添加索引

Python 创建表后向SQLAlchemy模型添加索引,python,indexing,sqlalchemy,Python,Indexing,Sqlalchemy,我有一个炼金术模型: class MyModel(db.Model): __tablename__ = 'targets' id = db.Column(db.Integer, primary_key=True) url = db.Column(db.String(2048)) 该表已创建,正在使用中。我想在url属性上创建一个索引,因此我将index=True传递给它: url = db.Column(db.String(2048), index=True) 在不删除和重新创建表格的情况下

我有一个炼金术模型:

class MyModel(db.Model):
__tablename__ = 'targets'
id = db.Column(db.Integer, primary_key=True)
url = db.Column(db.String(2048))
该表已创建,正在使用中。我想在url属性上创建一个索引,因此我将index=True传递给它:

url = db.Column(db.String(2048), index=True)

在不删除和重新创建表格的情况下,如何使此索引生效?

请注意,这是一个不正确且过于复杂的答案

正确的方法是使用
索引。如前所述创建


首先,确保您拥有数据库的最新快照,并且能够从此快照还原数据库

对于中型和大型项目(可能需要同时支持多个版本并安装在多个环境中的项目),有一个特殊的过程,它是数据库管理生命周期的一部分,称为“数据库迁移”。数据库迁移包括对现有架构的更改。SQLAlchemy不支持开箱即用的迁移

有两种与SQLAlchemy兼容的数据库迁移工具可用:

请参阅SQLAlchemy文档页面中的更多信息和指向这些工具的链接:

但如果您正在处理一个小项目,我建议您从数据库命令行实用程序或通过python脚本中的connection.execute()手动运行ALTER TABLE DDL查询

在我目前使用的生产应用程序中,我们只支持一个最新版本的应用程序。对于每个数据库架构更改,我们都执行以下步骤:

  • 制作生产数据库的快照
  • 在开发环境中加载此快照
  • 更新sqlalchemy数据模型模块
  • 准备并运行ALTERTABLE查询,并将此查询保存到以后
  • 对代码进行其他相关更改
  • 在dev环境上运行测试
  • 将最新版本的代码部署到生产环境中
  • 在生产过程中不要更改表格
此外,我还使用以下技巧生成创建表/索引查询: 我将我的应用程序指向全新的数据库,启用sqlalchemy查询的日志记录,并运行
元数据。create_all()
-因此在日志(或STDOUT)中,我看到了由sqlalchemy生成的create查询

根据您使用的数据库系统,索引创建查询将略有不同。 一般查询如下所示:

create index targets_i on targets(url);
class MyModel(db.Model):
    __tablename__ = 'targets'
    id = db.Column(db.Integer, primary_key=True)
    url = db.Column(db.String(2048))

mymodel_url_index = Index('mymodel_url_idx', MyModel.url)

if __name__ == '__main__':
    mymodel_url_index.create(bind=engine)
在索引上调用
create()

index.create()

给定原始问题中的模型类

class MyModel(db.Model):
    __tablename__ = 'targets'
    id = db.Column(db.Integer, primary_key=True)
    url = db.Column(db.String(2048))
不能只添加
index=True
,因为即使调用了
db.Model.metadata.create\u all()
也不会在已创建的表上创建索引

相反,您需要创建一个独立的
索引
对象,然后再创建它。它看起来像这样:

create index targets_i on targets(url);
class MyModel(db.Model):
    __tablename__ = 'targets'
    id = db.Column(db.Integer, primary_key=True)
    url = db.Column(db.String(2048))

mymodel_url_index = Index('mymodel_url_idx', MyModel.url)

if __name__ == '__main__':
    mymodel_url_index.create(bind=engine)

现在
引擎的来源将取决于您的sqlalchemy配置,但是这段代码应该传达需要发生的事情的要点。

我不确定这是否符合最佳实践,但我发现
Alembic
会通知我
\uuu table\u args\uuuu
中的索引,但实际上不会在迁移期间为我创建索引。我制作了这个小脚本,它可以生成
\uu table\u args\uu
属性中的新索引。如上所述,它使用
Index.create()
,但如果不存在新索引,则会生成新索引

def create_indexes(db, drop_index=False):
    """
    Creates all indexes on models in project if they do not exists already. Assumes all models
    inherit from RequiredFields class, otherwise will need to adjust search for subclasses. If the index
    exists SQLAlchemy throws an error and we assume everything is ok. 
    :param db: The app db object, acts as the engine param for the Index.create()
    :param drop_index: specifies whether the indexes should be dropped or created
    :return:
    """
    from application.base_models import RequiredFields
    from sqlalchemy import Index
    from sqlalchemy.exc import ProgrammingError
    for klass in RequiredFields.__subclasses__():
        if hasattr(klass, '__table_args__'):
            for item in getattr(klass, '__table_args__'):
                if isinstance(item, Index):
                    try:
                        if not drop_index:
                            item.create(db.engine)
                        else:
                            item.drop(db.engine)
                    except ProgrammingError:  # If index exists, creation fails on error
                        pass
    return
下面是一个显示索引的示例类

class MyModel(RequiredFields):

    __table_args__ = (
         db.Index( ... ),
         db.Index( ... ),
    )

用烧瓶,很酷。 添加索引后,只需使用以下命令:

python manage.py db migrate

一切正常

自提出问题以来,已添加对此的支持

现在,您只需将
index=True
添加到现有列中,并自动生成迁移

已检查以下软件包版本:

alembic==1.0.10
SQLAlchemy==1.3.4
SQLAlchemy-Utils==0.34.0
Flask-SQLAlchemy==2.4.0
Flask-Migrate==2.5.2

对不起,这个答案错了。ALTER TABLE不用于索引。SQLAlchemy非常直接地使用
INDEX.CREATE()
,以及
CreateIndex
DDL构造来支持“创建索引”,以实现更复杂的脚本编写情况。无需获取“create_all()”输出或诸如此类的内容。感谢您的指点。我同意——我描述了如何实现和支持有问题的方法。并且完全忘记了简单快捷的
索引。创建
。这个答案不知道从哪里可以从原始问题的代码中获取这个索引对象。在文档中爬行以找到这一点是很费劲的,老实说几乎没有什么帮助,因为它们没有涉及到使用声明性api(在最初的问题中使用了声明性api)。对于像我这样困惑,不想抓取文档和源代码的人,请参阅下面的答案。@PascalVKooten索引的名称:“mymodel\u url\u idx”(在本例中)可以设置为任何值,但必须在数据库中全局唯一。应该在何时执行
mymodel\u url\u index.create(bind=engine)
?如果我使用alembic?@learn2day
mymodel\u url\u index.create(bind=engine)
可以随时执行,但只能执行一次。运行该行将创建索引。我不能对alembic发表评论,因为我不知道它是如何工作的,但我希望migrations实用程序能够为您创建索引。我可以在中使用此方法创建的索引吗?如果是的话,我应该使用哪种语法?我真的很高兴看到这一点。我刚才尝试在相关的库中搜索此功能的引用,但找不到任何引用。我认为如果我/你/某人能够找到引用此功能的文档或变更日志的链接并将其包含在此处,这将非常有帮助。如果某人正在寻找支持此功能的资源,以下是索引API的文档。在第二个示例中,它显示了您可以这样做
Column(“name”,String(50),index=True)