Python Alembic为几何体列生成任意类型更改
我正在从事一个项目,该项目使用SQLite作为数据库,使用Alembic作为数据库迁移工具。它包括空间数据,因此,项目中包括空间扩展和Python Alembic为几何体列生成任意类型更改,python,sqlite,alembic,spatialite,geoalchemy2,Python,Sqlite,Alembic,Spatialite,Geoalchemy2,我正在从事一个项目,该项目使用SQLite作为数据库,使用Alembic作为数据库迁移工具。它包括空间数据,因此,项目中包括空间扩展和地球炼金术2。我正在使用autogenerate命令,它检测到几何体列中不存在的一些更改 以下是项目的简化结构: #模型 sqlite_命名_约定={ “ix”:“ix%(列0标签)s”, “uq”:“uq%(表名称)s%(列名称)s”, “ck”:“ck%(表名)s%(列名)s”, “fk”:“fk%(表名)s%(列名)s%(引用表名)s”, “主键”:“主键%
地球炼金术2
。我正在使用autogenerate
命令,它检测到几何体列中不存在的一些更改
以下是项目的简化结构:
#模型
sqlite_命名_约定={
“ix”:“ix%(列0标签)s”,
“uq”:“uq%(表名称)s%(列名称)s”,
“ck”:“ck%(表名)s%(列名)s”,
“fk”:“fk%(表名)s%(列名)s%(引用表名)s”,
“主键”:“主键%(表名)s”,
}
元数据=元数据(命名约定=sqlite命名约定)
BaseSpatiaLite=声明性_库(元数据=元数据)
类别几何图形(BaseSpatiaLite):
__tablename_=“几何图形”
几何图形\u id=列(整数,主键=真)
几何图形=柱(
地球炼金术2.types.Geometry(Geometry_type=“Geometry”,srid=4326,management=True),
nullable=False,
)
name=Column(字符串(长度=150),null=False)
Alembic的env.py
如下:
#env.py
...
def运行迁移在线()
可连接=引擎配置中的引擎配置(
config.get_节(config.config_ini_节),
prefix=“sqlalchemy.”,
poolclass=pool.NullPool,
)
#启用Spatialite扩展
监听(可连接,“连接”,加载空间)
#创建不存在的空间表
为sqlite创建空间表(可连接)
使用connectable.connect()作为连接:
context.configure(
连接=连接,
target\u metadata=target\u metadata,
将_渲染为_batch=True,
比较类型=真,
)
使用context.begin_transaction():
context.run_migrations()
创建几何图形表的第一个迁移脚本:
。。。
def升级():
op.create_表(
“几何学”,
sa.Column(“geometry_id”,sa.Integer(),nullable=False),
sa.Column(“geometry”,geoalchemy2.types.geometry(management=True),nullable=False),
sa.Column(“name”,sa.String(长度=150),nullable=False),
sa.PrimaryKeyConstraint(“几何体id”),
)
def降级():
op.drop_表(
“几何学”,
)
运行此迁移脚本后,将正确创建表:
当我再次运行autogenerate
命令时,它应该没有发现任何更改。但是,它会生成具有任意类型更改的迁移脚本:
def升级():
将op.batch_alter_table(“几何图形”,schema=None)作为batch_op:
批处理操作更改列(
“几何学”,
现有类型=sa.NUMERIC(),
类型=地球炼金术2.types.Geometry(srid=4326,management=True),
nullable=False,
)
def降级():
将op.batch_alter_table(“几何图形”,schema=None)作为batch_op:
批处理操作更改列(
“几何学”,
现有类型=地球炼金术2.types.Geometry(srid=4326,management=True),
类型=sa.NUMERIC(),
nullable=True,
)
我知道我可能会将
compare\u type
参数设置为False
,但我想自动检测类型更改。有没有办法告诉Alembic,geometry
列的类型是geometry
,并且没有任何变化?我找到了一个解决方案。我在这里分享它,以防其他人可能会遇到此错误:()
可以实现自定义的compare\u type
函数,并在env.py
中使用它。在我的例子中,geometry
列被解释为sqlalchemy.Integer
或sqalchemy.NUMERIC
类型。这就是为什么我添加了一个if子句,它返回False
如果检查类型为数值
或整数
,元数据类型为地球炼金术2.types.Geometry
# add it to env.py
def custom_compare_type(
context,
inspected_column,
metadata_column,
inspected_type,
metadata_type
):
# return False if the metadata_type is the same as the inspected_type
# or None to allow the default implementation to compare these
# types. a return value of True means the two types do not
# match and should result in a type change operation.
if (isinstance(inspected_type, NUMERIC) or isinstance(inspected_type, Integer)) and isinstance(
metadata_type, Geometry
):
return False
return None
当您将compare\u type=True
更改为compare\u type=custom\u compare\u type
时,Alembic应该停止检测几何体
列的任意类型更改
注意:Alembic仍然检测到可空性更改,但与compare\u type
问题无关