SQLAlchemy添加数据
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQLAlchemy添加数据相关的知识,希望对你有一定的参考价值。
两个表进行关联,添加数据时需要同时添加两个表的记录,但一个表的记录需要另一个表记录的ID值,这样用SQLAlchemy应该如何添加?
一般的做法应该是使用last insert id功能得到最近录入的记录ID,来作为另一个关系表的数据,但SQLAlchemy没有last insert id的功能。除了用SQL方法,有办法可以得到last insert id?
node = Node()
node.name = 'name'
db.session.add(node)
db.session.flush() # 主要是这里,写入数据库,但是不提交
this_id = node.id # 这样就可以获得自增id了
db.session.commit() 参考技术A
可以google/baidu搜索,或者到ChinaUnix的python社区下载如下教材:
简明Python教程
Python学习手册 第3版(Learning Python, 3rd Edition) 中文版
python语言从入门到精通
Python核心编程 第2版
看书配合练习,仅此而已追问
你答非所问,我问的是SQLAlchemy!
SqlAlchemy 将新字段添加到类并在表中创建相应的列
【中文标题】SqlAlchemy 将新字段添加到类并在表中创建相应的列【英文标题】:SqlAlchemy add new Field to class and create corresponding column in table 【发布时间】:2010-01-20 17:01:53 【问题描述】:我想向现有的映射类添加一个字段,我将如何自动更新 sql 表。如果将字段添加到类中,sqlalchemy 是否提供使用新列更新数据库的方法。
【问题讨论】:
【参考方案1】:有时迁移工作量太大 - 您只想在运行更改的代码时自动添加列。所以这里有一个函数可以做到这一点。
注意事项:它涉及 SQLAlchemy 内部结构,并且在每次 SQLAlchemy 进行重大修订时往往需要进行小的更改。 (这样做可能有更好的方法——我不是 SQLAlchemy 专家)。它也不处理约束。
import logging
import re
import sqlalchemy
from sqlalchemy import MetaData, Table, exceptions
import sqlalchemy.engine.ddl
_new_sa_ddl = sqlalchemy.__version__.startswith('0.7')
def create_and_upgrade(engine, metadata):
"""For each table in metadata, if it is not in the database then create it.
If it is in the database then add any missing columns and warn about any columns
whose spec has changed"""
db_metadata = MetaData()
db_metadata.bind = engine
for model_table in metadata.sorted_tables:
try:
db_table = Table(model_table.name, db_metadata, autoload=True)
except exceptions.NoSuchTableError:
logging.info('Creating table %s' % model_table.name)
model_table.create(bind=engine)
else:
if _new_sa_ddl:
ddl_c = engine.dialect.ddl_compiler(engine.dialect, None)
else:
# 0.6
ddl_c = engine.dialect.ddl_compiler(engine.dialect, db_table)
# else:
# 0.5
# ddl_c = engine.dialect.schemagenerator(engine.dialect, engine.contextual_connect())
logging.debug('Table %s already exists. Checking for missing columns' % model_table.name)
model_columns = _column_names(model_table)
db_columns = _column_names(db_table)
to_create = model_columns - db_columns
to_remove = db_columns - model_columns
to_check = db_columns.intersection(model_columns)
for c in to_create:
model_column = getattr(model_table.c, c)
logging.info('Adding column %s.%s' % (model_table.name, model_column.name))
assert not model_column.constraints, \
'Arrrgh! I cannot automatically add columns with constraints to the database'\
'Please consider fixing me if you care!'
model_col_spec = ddl_c.get_column_specification(model_column)
sql = 'ALTER TABLE %s ADD %s' % (model_table.name, model_col_spec)
engine.execute(sql)
# It's difficult to reliably determine if the model has changed
# a column definition. E.g. the default precision of columns
# is None, which means the database decides. Therefore when I look at the model
# it may give the SQL for the column as INTEGER but when I look at the database
# I have a definite precision, therefore the returned type is INTEGER(11)
for c in to_check:
model_column = model_table.c[c]
db_column = db_table.c[c]
x = model_column == db_column
logging.debug('Checking column %s.%s' % (model_table.name, model_column.name))
model_col_spec = ddl_c.get_column_specification(model_column)
db_col_spec = ddl_c.get_column_specification(db_column)
model_col_spec = re.sub('[(][\d ,]+[)]', '', model_col_spec)
db_col_spec = re.sub('[(][\d ,]+[)]', '', db_col_spec)
db_col_spec = db_col_spec.replace('DECIMAL', 'NUMERIC')
db_col_spec = db_col_spec.replace('TINYINT', 'BOOL')
if model_col_spec != db_col_spec:
logging.warning('Column %s.%s has specification %r in the model but %r in the database' %
(model_table.name, model_column.name, model_col_spec, db_col_spec))
if model_column.constraints or db_column.constraints:
# TODO, check constraints
logging.debug('Column constraints not checked. I am too dumb')
for c in to_remove:
model_column = getattr(db_table.c, c)
logging.warning('Column %s.%s in the database is not in the model' % (model_table.name, model_column.name))
def _column_names(table):
# Autoloaded columns return unicode column names - make sure we treat all are equal
return set((unicode(i.name) for i in table.c))
【讨论】:
非常感谢!正是我想要的。【参考方案2】:SQLAlchemy 本身不支持架构的自动更新,但是有一个第三方SQLAlchemy Migrate 工具可以自动迁移。看看"Database schema versioning workflow" chapter 看看它是如何工作的。
【讨论】:
我可以要求一个新的链接吗?那个人似乎已经死了。提前致谢。 Alembic 取代了 SQLAlchemy-Migrate 项目,该项目是 SQLAlchemy 的原始迁移工具,现在被视为旧版。【参考方案3】:Alembic 是提供数据库迁移的最新软件包。
见sqlalchemy docs regarding migration here。
【讨论】:
【参考方案4】:# database.py has definition for engine.
# from sqlalchemy import create_engine
# engine = create_engine('mysql://......', convert_unicode=True)
from database import engine
from sqlalchemy import DDL
add_column = DDL('ALTER TABLE USERS ADD COLUMN city VARCHAR(60) AFTER email')
engine.execute(add_column)
【讨论】:
【参考方案5】:可以使用 sqlalchemy-migrate 但实际上不使用迁移:
sqlalchemy.MetaData(bind=dbinterface.db.engine)
table = sqlalchemy.schema.Table(table_name, meta_data)
try:
col = sqlalchemy.Column('column_name', sqlalchemy.String)
col.create(table)
except Exception as e:
print "Error adding column: ".format(e)
要与 python 3 一起使用,我需要 sqlalchemy-migrate==0.12.0。
【讨论】:
【参考方案6】:您可以安装“DB Browser (SQLite)”并打开您当前的数据库文件并在您的数据库中简单地添加/编辑表并保存它,然后运行您的应用程序 (保存上述过程后在模型中添加脚本)
【讨论】:
以上是关于SQLAlchemy添加数据的主要内容,如果未能解决你的问题,请参考以下文章
我可以根据 SQLAlchemy 中的另一个数据库行添加新项目吗?
有没有办法在烧瓶 sqlalchemy 连接中添加 mySQL 数据库/模式名称