flask_migrate结合geoalchemy2迁移postgis

2024-04-01 00:48

本文主要是介绍flask_migrate结合geoalchemy2迁移postgis,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

代码示例

创建app.py

from flask import Flask
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
from geoalchemy2 import Geometryapp = Flask(__name__)app.config['SQLALCHEMY_DATABASE_URI'] = "postgresql://postgres:111111@localhost:5432/postgres"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = Falsedb = SQLAlchemy(app)
Migrate(app, db)class Point(db.Model):id = db.Column(db.Integer, primary_key=True, autoincrement=True)geom = db.Column(Geometry("POINT", srid=4326, spatial_index=False))# 正确创建空间索引的方式:指定spatial_index=False,并使用以下方式创建空间索引,否则使用flask_migrate会重复创建索引导致报错
# 参考链接:https://github.com/geoalchemy/geoalchemy2/issues/137#issuecomment-1022413828
db.Index("idx_point_geom",Target.__table__.c.geom,postgresql_using='gist',
)@app.route('/')
def index():return "<h1>hello</h1>"if __name__ == '__main__':app.run(debug=True)

迁移

flask db init

输出:

Creating directory /test/migrations ...  done
Creating directory /test/migrations/versions ...  done
Generating /test/migrations/alembic.ini ...  done
Generating /test/migrations/env.py ...  done
Generating /test/migrations/README ...  done
Generating /test/migrations/script.py.mako ...  done
Please edit configuration/connection/logging settings in '/test/migrations/alembic.ini' before proceeding.
flask db migrate

输出:

INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added table 'point'
INFO  [alembic.autogenerate.compare] Detected removed table 'spatial_ref_sys'
Generating /test/migrations/versions/419c1d992227_.py ...  done
flask db upgrade

输出:

INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade  -> 419c1d992227, empty message...File "/test/migrations/versions/419c1d992227_.py", line 23, in upgradesa.Column('geom', geoalchemy2.types.Geometry(geometry_type='POINT', srid=4326, from_text='ST_GeomFromEWKT', name='geometry'), nullable=True),
NameError: name 'geoalchemy2' is not defined

错误分析

发现/test/migrations/versions/419c1d992227_.py中的geoalchemy2没有导入,并且spatial_ref_sys表也不应该被删除,否则将无法使用空间扩展
在这里插入图片描述

解决方案

方法一(推荐):使用geoalchemy2中的alembic_helpers

...
from geoalchemy2.alembic_helpers import include_object, render_itemfrom app import create_app
from app.model import dbapp = create_app()# compare_server_default=True
migrate = Migrate(app, db, compare_type=True, include_object=include_object, render_item=render_item)

方法二:手动编辑

每次迁移完后修改迁移脚本,如下:
在这里插入图片描述
再执行flask db upgrade,输出:

INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade  -> 419c1d992227, empty message

迁移成功

修改模板

script.py.mako中添加import geoalchemy2,如下所示:

"""${message}Revision ID: ${up_revision}
Revises: ${down_revision | comma,n}
Create Date: ${create_date}"""
from alembic import op
import sqlalchemy as sa
import geoalchemy2
${imports if imports else ""}# revision identifiers, used by Alembic.
revision = ${repr(up_revision)}
down_revision = ${repr(down_revision)}
branch_labels = ${repr(branch_labels)}
depends_on = ${repr(depends_on)}def upgrade():${upgrades if upgrades else "pass"}def downgrade():${downgrades if downgrades else "pass"}

env.py中添加include_object函数,忽略spatial_ref_sys表,并在context.configure中添加include_object=include_object,如下所示:

...def include_object(object, name, type_, reflected, compare_to):if type_ == 'table' and name in ('spatial_ref_sys'):return Falsereturn Truedef run_migrations_online():"""Run migrations in 'online' mode.In this scenario we need to create an Engineand associate a connection with the context."""# this callback is used to prevent an auto-migration from being generated# when there are no changes to the schema# reference: http://alembic.zzzcomputing.com/en/latest/cookbook.htmldef process_revision_directives(context, revision, directives):if getattr(config.cmd_opts, 'autogenerate', False):script = directives[0]if script.upgrade_ops.is_empty():directives[:] = []logger.info('No changes in schema detected.')connectable = current_app.extensions['migrate'].db.enginewith connectable.connect() as connection:context.configure(connection=connection,target_metadata=target_metadata,process_revision_directives=process_revision_directives,include_object=include_object,**current_app.extensions['migrate'].configure_args)with context.begin_transaction():context.run_migrations()...       

此方法只在数据库迁移前修改一次,随后可直接进行数据库迁移。

升级

接下来我们来添加一个Polygon

class Polygon(db.Model):id = db.Column(db.Integer, primary_key=True, autoincrement=True)geom = db.Column(Geometry("POLYGON", srid=4326))

迁移后脚本如下:

def upgrade():# ### commands auto generated by Alembic - please adjust! ###op.create_table('polygon',sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),sa.Column('geom', geoalchemy2.types.Geometry(geometry_type='POLYGON', srid=4326, from_text='ST_GeomFromEWKT', name='geometry'), nullable=True),sa.PrimaryKeyConstraint('id'))op.drop_index('idx_point_geom', table_name='point')# ### end Alembic commands ###

其中op.drop_index('idx_point_geom', table_name='point')显然是不对的,因为此操作将会删除空间索引,这不是我们想要的。
回到env.py,添加index判断:

def include_object(object, name, type_, reflected, compare_to):if type_ == 'table' and name in ('spatial_ref_sys'):return Falseif type_ == 'index' and name.endswith("_geom"):return Falsereturn True

总结

  • 在生产环境中,migrations目录应该作为持久化数据永久存储!
  • 对于永久不变的数据库迁移推荐使用db.create_all(),免去了复杂的配置
  • 对于需要添加字段或者新增表的数据库迁移推荐使用修改模板方式,一次配置永久有效

参考链接:

  • https://alembic.sqlalchemy.org/en/latest/autogenerate.html#omitting-table-names-from-the-autogenerate-process
  • https://geoalchemy-2.readthedocs.io/en/latest/alembic.html

这篇关于flask_migrate结合geoalchemy2迁移postgis的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/865810

相关文章

CentOs7上Mysql快速迁移脚本

因公司业务需要,对原来在/usr/local/mysql/data目录下的数据迁移到/data/local/mysql/mysqlData。 原因是系统盘太小,只有20G,几下就快满了。 参考过几篇文章,基于大神们的思路,我封装成了.sh脚本。 步骤如下: 1) 先修改好/etc/my.cnf,        ##[mysqld]       ##datadir=/data/loc

CentOS下mysql数据库data目录迁移

https://my.oschina.net/u/873762/blog/180388        公司新上线一个资讯网站,独立主机,raid5,lamp架构。由于资讯网是面向小行业,初步估计一两年内访问量压力不大,故,在做服务器系统搭建的时候,只是简单分出一个独立的data区作为数据库和网站程序的专区,其他按照linux的默认分区。apache,mysql,php均使用yum安装(也尝试

Linux Centos 迁移Mysql 数据位置

转自:http://www.tuicool.com/articles/zmqIn2 由于业务量增加导致安装在系统盘(20G)磁盘空间被占满了, 现在进行数据库的迁移. Mysql 是通过 yum 安装的. Centos6.5Mysql5.1 yum 安装的 mysql 服务 查看 mysql 的安装路径 执行查询 SQL show variables like

Go 语言中Select与for结合使用break

func test(){i := 0for {select {case <-time.After(time.Second * time.Duration(2)):i++if i == 5{fmt.Println("break now")break }fmt.Println("inside the select: ")}fmt.Println("inside the for: ")}} 执行后

Jenkins--pipeline认识及与RF文件的结合应用

什么是pipeline? Pipeline,就是可运行在Jenkins上的工作流框架,将原本独立运行的单个或多个节点任务连接起来,实现单个任务难以完成的复杂流程编排与可视化。 为什么要使用pipeline? 1.流程可视化显示 2.可自定义流程任务 3.所有步骤代码化实现 如何使用pipeline 首先需要安装pipeline插件: 流水线有声明式和脚本式的流水线语法 流水线结构介绍 Node:

风格控制水平创新高!南理工InstantX小红书发布CSGO:简单高效的端到端风格迁移框架

论文链接:https://arxiv.org/pdf/2408.16766 项目链接:https://csgo-gen.github.io/ 亮点直击 构建了一个专门用于风格迁移的数据集设计了一个简单但有效的端到端训练的风格迁移框架CSGO框架,以验证这个大规模数据集在风格迁移中的有益效果。引入了内容对齐评分(Content Alignment Score,简称CAS)来评估风格迁移

DataGrip数据迁移

第一步 第二步  第三步  第四步 选择你刚刚到处的文件即可

flask-login 生成 cookie,session

flask-login 生成 cookie,session Flask-Login login_user() 显示来自 Set-Cookie 标头的加密 cookie # 模拟一个用户类class User(UserMixin):def __init__(self, id):self.id = id@app.route('/login')def login():# 模拟用户登录过程user

Flask 创建app 时候传入的 static_folder 和 static_url_path参数理解

Flask 在创建app的时候 是用 app = Flask(__name__) 来创建的,不传入 static_folder参数的话 ,默认的静态文件的位置是在 static目录下 我们可以进入 Flask的源码里面查看 ctrl+鼠标左键进入 这是Flask的 __init__源码(后面还有一些,我就选了需要的代码)     def __init__(self,import_

结合Python与GUI实现比赛预测与游戏数据分析

在现代软件开发中,用户界面设计和数据处理紧密结合,以提升用户体验和功能性。本篇博客将基于Python代码和相关数据分析进行讨论,尤其是如何通过PyQt5等图形界面库实现交互式功能。同时,我们将探讨如何通过嵌入式预测模型为用户提供赛果预测服务。 本文的主要内容包括: 基于PyQt5的图形用户界面设计。结合数据进行比赛预测。文件处理和数据分析流程。 1. PyQt5 图形用户界面设计