前言
最近在用SQLAlchemy处理数据库相关的事情,在网上找到了一篇关于SQLAlchemy基本用法的Cheatsheet,自己跑了一下,发现其中还有一些Bugs,做了一点改正,记录下来。
注意
文中的所有用法以PostgreSQL为例,并进行测试。对于其他类型的数据库,个别特殊的地方可能需要修改。
Set a database URL
1 from sqlalchemy.engine.url import URL
1 2 3 4 5 6 7 8 9 postgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) print (db_url)
postgres+psycopg2://postgres:postgres@localhost:5432/example
1 from sqlalchemy import create_engine
Note that the Engine and its underlying Pool do not establish the first actual DBAPI connection until the Engine.connect() method is called, or an operation which is dependent on this method such as Engine.execute() is invoked. In this way, Engine and Pool can be said to have a lazy initialization behavior.
Create a Database (For postgresql only)
方法一:利用底层连接
在Postgres上,默认情况下有三个数据库。如果您能够以超级用户的身份进行连接(例如,postgres),则可以连接到postgres或template1数据库。默认pg_conf只允许名为postgres使用postgres角色,所以最简单的事情就是成为那个用户。无论如何,与通常一样,与具有创建数据库权限的用户一起创建一个引擎:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 no_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : None , 'query' : None } no_db_url = URL(**no_db) engine = create_engine(no_db_url) conn = engine.connect() conn.execute("commit" ) conn.execute("create database example" ) conn.close() engine.dispose()
方法二:采用sqlalchemy_utils
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 from sqlalchemy_utils import database_exists, create_database,drop_databaseno_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'no_db' , 'query' : None } no_db_url = URL(**no_db) engine = create_engine(no_db_url) print (database_exists(engine.url))if database_exists(engine.url): drop_database(no_db_url) print (database_exists(engine.url)) if not database_exists(engine.url): create_database(engine.url) print (database_exists(engine.url))if database_exists(engine.url): drop_database(no_db_url) print (database_exists(engine.url))engine.dispose()
False
True
False
Sqlalchemy Support DBAPI - PEP249
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 from sqlalchemy import create_enginepostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) engine.execute('CREATE TABLE "EX1" (' 'id INTEGER NOT NULL,' 'name VARCHAR, ' 'PRIMARY KEY (id));' ) engine.execute('INSERT INTO "EX1" ' '(id, name) ' 'VALUES (1, \'raw1\')' ) result = engine.execute('SELECT * FROM ' '"EX1"' ) for _r in result: print (_r) engine.execute('DELETE from "EX1" where id=1;' ) result = engine.execute('SELECT * FROM "EX1"' ) print (result.fetchall())engine.dispose()
(1, 'raw1')
[]
Transaction and Connect Object
单引号 (') 和双引号 (") 在 PostgreSQL 中有明确的区分,单引号用来引用值 (value),而双引号用来引用标识符,如字段名,表名等等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 from sqlalchemy import create_enginepostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) conn = engine.connect() trans = conn.begin() conn.execute('INSERT INTO "EX1" (id, name) ' 'VALUES (2, \'Hello\')' ) trans.commit() conn.close() engine.dispose()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 from sqlalchemy import create_enginefrom sqlalchemy import MetaDatafrom sqlalchemy import Tablefrom sqlalchemy import Columnfrom sqlalchemy import Integer, Stringpostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) metadata = MetaData(engine) table = Table('SubExample' ,metadata, Column('id' ,Integer, primary_key=True ), Column('name' ,String)) metadata.create_all() for _t in metadata.tables: print ("Table: " , _t)
Table: SubExample
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from sqlalchemy import create_enginefrom sqlalchemy import inspectpostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) inspector = inspect(engine) print (inspector.get_table_names())print (inspector.get_columns('EX1' ))print ([item['name' ] for item in inspector.get_columns('SubExample' )])
['EX1', 'SubExample']
[{'name': 'id', 'type': INTEGER(), 'nullable': False, 'default': None, 'autoincrement': False, 'comment': None}, {'name': 'name', 'type': VARCHAR(), 'nullable': True, 'default': None, 'autoincrement': False, 'comment': None}]
['id', 'name']
Reflection - Loading Table from Existing Database
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 from sqlalchemy import create_enginefrom sqlalchemy import MetaDatafrom sqlalchemy import Tablepostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) metadata = MetaData() print (metadata.tables)metadata.reflect(bind=engine) print (metadata.tables)
immutabledict({})
immutabledict({'EX1': Table('EX1', MetaData(bind=None), Column('id', INTEGER(), table=<EX1>, primary_key=True, nullable=False), Column('name', VARCHAR(), table=<EX1>), schema=None), 'SubExample': Table('SubExample', MetaData(bind=None), Column('id', INTEGER(), table=<SubExample>, primary_key=True, nullable=False, server_default=DefaultClause(<sqlalchemy.sql.elements.TextClause object at 0x000001AEF1F68370>, for_update=False)), Column('name', VARCHAR(), table=<SubExample>), schema=None)})
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 from sqlalchemy import create_enginefrom sqlalchemy import MetaDatafrom sqlalchemy import Tablepostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) metadata = MetaData(bind=engine) metadata.reflect() table = metadata.tables['EX1' ] print (table.columns)
['EX1.id', 'EX1.name']
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 from sqlalchemy import create_enginefrom sqlalchemy import MetaDatafrom sqlalchemy import Tablepostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) metadata = MetaData(engine) t1 = Table('EX1' , metadata, Column('id' ,Integer, primary_key=True ), Column('name' ,String)) t2 = Table('EX2' , metadata, Column('id' ,Integer, primary_key=True ), Column('val' ,Integer)) metadata.create_all() engine.dispose()
Create Specific Table
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 from sqlalchemy import create_enginefrom sqlalchemy import MetaDatafrom sqlalchemy import Tablepostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) metadata = MetaData(engine) t3 = Table('EX3' , metadata, Column('id' ,Integer, primary_key=True ), Column('name' ,String)) t3.create() engine.dispose()
Create table with same columns
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 from sqlalchemy import ( create_engine, inspect, Column, String, Integer) from sqlalchemy.ext.declarative import declarative_basepostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) Base = declarative_base() class TemplateTable (object ): id = Column(Integer, primary_key=True ) name = Column(String) age = Column(Integer) class DowntownAPeople (TemplateTable, Base): __tablename__ = "downtown_a_people" class DowntownBPeople (TemplateTable, Base): __tablename__ = "downtown_b_people" Base.metadata.create_all(bind=engine) inspector = inspect(engine) print (inspector.get_table_names())engine.dispose()
['EX1', 'SubExample', 'EX2', 'EX3', 'downtown_a_people', 'downtown_b_people']
Drop a table
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 from sqlalchemy import ( create_engine, inspect, Column, String, Integer) from sqlalchemy.ext.declarative import declarative_basepostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) metadata = MetaData() table = Table('Test' , metadata, Column('id' , Integer, primary_key=True ), Column('key' , String, nullable=True ), Column('val' , String)) table.create(engine) inspector = inspect(engine) print ('Test' in inspector.get_table_names())table.drop(engine) inspector = inspect(engine) print ('Test' in inspector.get_table_names())engine.dispose()
True
False
Some Table Object Operation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 from sqlalchemy import ( create_engine, inspect, Column, String, Integer) from sqlalchemy.ext.declarative import declarative_basepostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) metadata = MetaData() t = Table('ex_table' , metadata, Column('id' , Integer, primary_key=True ), Column('key' , String), Column('val' , Integer)) print (t.name)print (t.columns.keys())c = t.c.key print (c.name)c = t.columns.key print (c.name)print (c.table)engine.dispose()
ex_table
['id', 'key', 'val']
key
key
ex_table
SQL Expression Language
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 from sqlalchemy import MetaDatafrom sqlalchemy import Tablefrom sqlalchemy import Columnfrom sqlalchemy import Integer, Stringfrom sqlalchemy import or_postgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) metadata = MetaData() table = Table('example' , metadata, Column('id' , Integer, primary_key=True ), Column('l_name' , String), Column('f_name' , String)) print (repr (table.c.l_name == 'ed' ))print (str (table.c.l_name == 'ed' ))print (repr (table.c.f_name != 'ed' ))print (repr (table.c.id > 3 ))print ((table.c.id > 5 ) | (table.c.id < 2 ))print (or_(table.c.id > 5 , table.c.id < 2 ))print (table.c.l_name == None )print (table.c.l_name.is_(None ))print (table.c.id + 5 )print (table.c.l_name + "some name" )print (table.c.l_name.in_(['a' ,'b' ]))engine.dispose()
<sqlalchemy.sql.elements.BinaryExpression object at 0x000001AEF238F100>
example.l_name = :l_name_1
<sqlalchemy.sql.elements.BinaryExpression object at 0x000001AEF2297D90>
<sqlalchemy.sql.elements.BinaryExpression object at 0x000001AEF234D4C0>
example.id > :id_1 OR example.id < :id_2
example.id > :id_1 OR example.id < :id_2
example.l_name IS NULL
example.l_name IS NULL
example.id + :id_1
example.l_name || :l_name_1
example.l_name IN (:l_name_1, :l_name_2)
insert() - Create an “INSERT” Statement
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 from sqlalchemy import create_enginefrom sqlalchemy import MetaDatafrom sqlalchemy import Tablefrom sqlalchemy import Columnfrom sqlalchemy import Integerfrom sqlalchemy import Stringpostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) metadata = MetaData(engine) table = Table('user' , metadata, Column('id' , Integer, primary_key=True ), Column('l_name' , String), Column('f_name' , String)) metadata.create_all() ins = table.insert().values( l_name='Hello' , f_name='World' ) conn = engine.connect() conn.execute(ins) conn.execute(table.insert(),[ {'l_name' :'Hi' ,'f_name' :'bob' }, {'l_name' :'yo' ,'f_name' :'alice' }]) conn.close() engine.dispose()
select() - Create a “SELECT” Statement
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 from sqlalchemy import create_enginefrom sqlalchemy import MetaDatafrom sqlalchemy import Tablefrom sqlalchemy import selectfrom sqlalchemy import or_postgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) conn = engine.connect() metadata = MetaData(engine) metadata.reflect() table = metadata.tables['user' ] select_st = select([table]).where( table.c.l_name == 'Hello' ) res = conn.execute(select_st) for _row in res: print (_row) select_st = table.select().where( table.c.l_name == 'Hello' ) res = conn.execute(select_st) for _row in res: print (_row) select_st = select([ table.c.l_name, table.c.f_name]).where(or_( table.c.l_name == 'Hello' , table.c.l_name == 'Hi' )) res = conn.execute(select_st) for _row in res: print (_row) select_st = select([table]).where(or_( table.c.l_name == 'Hello' , table.c.l_name == 'Hi' )).order_by(table.c.f_name) res = conn.execute(select_st) for _row in res: print (_row) conn.close() engine.dispose()
(1, 'Hello', 'World')
(1, 'Hello', 'World')
('Hello', 'World')
('Hi', 'bob')
(2, 'Hi', 'bob')
(1, 'Hello', 'World')
join() - Joined Two Tables via “JOIN” Statement
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 from sqlalchemy import create_enginefrom sqlalchemy import MetaDatafrom sqlalchemy import Tablefrom sqlalchemy import Columnfrom sqlalchemy import Integerfrom sqlalchemy import Stringfrom sqlalchemy import selectpostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) conn = engine.connect() metadata = MetaData(engine) metadata.reflect() email_t = Table('email_addr' , metadata, Column('id' , Integer, primary_key=True ), Column('email' ,String), Column('name' ,String)) metadata.create_all() user_t = metadata.tables['user' ] conn = engine.connect() conn.execute(email_t.insert(),[ {'email' :'ker@test' ,'name' :'Hi' }, {'email' :'yo@test' ,'name' :'Hello' }]) join_obj = user_t.join(email_t, email_t.c.name == user_t.c.l_name) sel_st = select( [user_t.c.l_name, email_t.c.email]).select_from(join_obj) res = conn.execute(sel_st) for _row in res: print (_row) conn.close() engine.dispose()
('Hello', 'yo@test')
('Hi', 'ker@test')
Delete Rows from Table
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 from sqlalchemy import create_enginefrom sqlalchemy import MetaDatapostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) conn = engine.connect() metadata = MetaData(engine) metadata.reflect() user_t = metadata.tables['user' ] sel_st = user_t.select() res = conn.execute(sel_st) for _row in res: print (_row) del_st = user_t.delete().where( user_t.c.l_name == 'Hello' ) print ('----- delete -----' )res = conn.execute(del_st) sel_st = user_t.select() res = conn.execute(sel_st) for _row in res: print (_row) conn.close() engine.dispose()
(1, 'Hello', 'World')
(2, 'Hi', 'bob')
(3, 'yo', 'alice')
----- delete -----
(2, 'Hi', 'bob')
(3, 'yo', 'alice')
Check Table Existing
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 from sqlalchemy import create_enginefrom sqlalchemy import MetaDatafrom sqlalchemy import Columnfrom sqlalchemy import Integer, Stringfrom sqlalchemy import inspectfrom sqlalchemy.ext.declarative import declarative_baseModal = declarative_base() class Example (Modal ): __tablename__ = "ex_t" id = Column(Integer, primary_key=True ) name = Column(String(20 )) postgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) conn = engine.connect() for _t in Modal.metadata.tables: print (_t) print ('-' *50 )metadata = MetaData(engine) metadata.reflect() for _t in metadata.tables: print (_t) print ('-' *50 )Modal.metadata.create_all(engine) ins = inspect(engine) for _t in ins.get_table_names(): print (_t) conn.close() engine.dispose()
ex_t
--------------------------------------------------
EX1
user
SubExample
email_addr
EX2
EX3
downtown_a_people
downtown_b_people
--------------------------------------------------
EX1
user
SubExample
email_addr
EX2
ex_t
EX3
downtown_a_people
downtown_b_people
Create multiple tables at once
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 from sqlalchemy import create_enginefrom sqlalchemy import MetaDatafrom sqlalchemy import Tablefrom sqlalchemy import inspectfrom sqlalchemy import Column, String, Integerfrom sqlalchemy.engine.url import URLpostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) conn = engine.connect() metadata = MetaData(engine) metadata.reflect() def create_table (name, metadata ): tables = metadata.tables.keys() if name not in tables: table = Table(name, metadata, Column('id' , Integer, primary_key=True ), Column('key' , String), Column('val' , Integer)) table.create(engine) tables = ['table1' , 'table2' , 'table3' ] for _t in tables: create_table(_t, metadata)inspector = inspect(engine) print (inspector.get_table_names())conn.close() engine.dispose()
['EX1', 'user', 'SubExample', 'email_addr', 'EX2', 'ex_t', 'EX3', 'table1', 'table2', 'table3', 'downtown_a_people', 'downtown_b_people']
Create tables with dynamic columns (Table)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 from sqlalchemy import create_enginefrom sqlalchemy import Column, Integer, Stringfrom sqlalchemy import Tablefrom sqlalchemy import MetaDatafrom sqlalchemy import inspectfrom sqlalchemy.engine.url import URLpostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) def create_table (name, *cols ): metadata = MetaData(bind=engine) metadata.reflect() if name in metadata.tables: return table = Table(name, metadata, *cols) table.create(engine) create_table('Table1' , Column('id' , Integer, primary_key=True ), Column('name' , String)) create_table('Table2' , Column('id' , Integer, primary_key=True ), Column('key' , String), Column('val' , String)) inspector = inspect(engine) for _t in inspector.get_table_names(): print (_t) engine.dispose()
EX1
user
SubExample
email_addr
EX2
ex_t
EX3
table1
table2
table3
downtown_a_people
downtown_b_people
Table1
Table2
Object Relational add data
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 from datetime import datetimefrom sqlalchemy import create_enginefrom sqlalchemy import Column, Integer, String, DateTimefrom sqlalchemy.orm import sessionmakerfrom sqlalchemy.exc import SQLAlchemyErrorfrom sqlalchemy.ext.declarative import declarative_basefrom sqlalchemy.engine.url import URLpostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) Base = declarative_base() class TestTable (Base ): __tablename__ = 'Test Table' id = Column(Integer, primary_key=True ) key = Column(String, nullable=False ) val = Column(String) date = Column(DateTime, default=datetime.utcnow) Base.metadata.create_all(bind=engine) Session = sessionmaker() Session.configure(bind=engine) session = Session() data = {'a' : 5566 , 'b' : 9527 , 'c' : 183 } try : for _key, _val in data.items(): row = TestTable(key=_key, val=_val) session.add(row) session.commit() except SQLAlchemyError as e: print (e) finally : session.close() engine.dispose()
Object Relational update data
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 from datetime import datetimefrom sqlalchemy import create_enginefrom sqlalchemy import Column, Integer, String, DateTimefrom sqlalchemy.orm import sessionmakerfrom sqlalchemy.exc import SQLAlchemyErrorfrom sqlalchemy.ext.declarative import declarative_basefrom sqlalchemy.engine.url import URLpostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) Base = declarative_base() class TestTable (Base ): __tablename__ = 'Test Table' id = Column(Integer, primary_key=True ) key = Column(String, nullable=False ) val = Column(String) date = Column(DateTime, default=datetime.utcnow) Base.metadata.create_all(bind=engine) Session = sessionmaker() Session.configure(bind=engine) session = Session() try : row = TestTable(key="hello" , val="world" ) session.add(row) session.commit() row = session.query(TestTable).filter ( TestTable.key == 'hello' ).first() print ('original:' , row.key, row.val) row.key = "Hello" row.val = "World" session.commit() row = session.query(TestTable).filter ( TestTable.key == 'Hello' ).first() print ('update:' , row.key, row.val) except SQLAlchemyError as e: print (e) finally : session.close() engine.dispose()
original: hello world
update: Hello World
Object Relational delete row
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 from datetime import datetimefrom sqlalchemy import create_enginefrom sqlalchemy import Column, Integer, String, DateTimefrom sqlalchemy.orm import sessionmakerfrom sqlalchemy.exc import SQLAlchemyErrorfrom sqlalchemy.ext.declarative import declarative_basefrom sqlalchemy.engine.url import URLpostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) Base = declarative_base() class TestTable (Base ): __tablename__ = 'Test Table' id = Column(Integer, primary_key=True ) key = Column(String, nullable=False ) val = Column(String) date = Column(DateTime, default=datetime.utcnow) Base.metadata.create_all(bind=engine) Session = sessionmaker() Session.configure(bind=engine) session = Session() row = TestTable(key='hello' , val='world' ) session.add(row) query = session.query(TestTable).filter ( TestTable.key=='hello' ) print (query.first().id )query.delete() query = session.query(TestTable).filter ( TestTable.key=='hello' ) session.commit() print ([q.id for q in query.all ()])session.close() engine.dispose()
5
[]
Object Relational relationship
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 from sqlalchemy import Column, String, Integer, ForeignKeyfrom sqlalchemy.orm import relationshipfrom sqlalchemy.ext.declarative import declarative_baseBase = declarative_base() class User (Base ): __tablename__ = 'user' id = Column(Integer, primary_key=True ) name = Column(String) addresses = relationship("Address" , backref="user" ) class Address (Base ): __tablename__ = 'address' id = Column(Integer, primary_key=True ) email = Column(String) user_id = Column(Integer, ForeignKey('user.id' )) a1 = Address(email='[email protected] ' ) u1 = User(name='user2' ) print (u1.addresses)print (a1.user)u1.addresses.append(a1) print ([a.email for a in u1.addresses])print (a1.user.name)
[]
None
['[email protected] ']
user2
Object Relational self association
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 import jsonfrom sqlalchemy import ( Column, Integer, String, ForeignKey, Table) from sqlalchemy.orm import ( sessionmaker, relationship) from sqlalchemy.ext.declarative import declarative_baseBase = declarative_base() association = Table("Association" , Base.metadata, Column('left' , Integer, ForeignKey('node.id' ), primary_key=True ), Column('right' , Integer, ForeignKey('node.id' ), primary_key=True )) class Node (Base ): __tablename__ = 'node' id = Column(Integer, primary_key=True ) label = Column(String) friends = relationship('Node' , secondary=association, primaryjoin=id ==association.c.left, secondaryjoin=id ==association.c.right, backref='left' ) def to_json (self ): return dict (id =self.id , friends=[_.label for _ in self.friends]) nodes = [Node(label='node_{}' .format (_)) for _ in range (0 , 3 )] nodes[0 ].friends.extend([nodes[1 ], nodes[2 ]]) nodes[1 ].friends.append(nodes[2 ]) print ('--------------------> right' )print (json.dumps([_.to_json() for _ in nodes], indent=2 ))print ('--------------------> left' )print (json.dumps([_n.to_json() for _n in nodes[1 ].left], indent=2 ))
--------------------> right
[
{
"id": null,
"friends": [
"node_1",
"node_2"
]
},
{
"id": null,
"friends": [
"node_2"
]
},
{
"id": null,
"friends": []
}
]
--------------------> left
[
{
"id": null,
"friends": [
"node_1",
"node_2"
]
}
]
Object Relational basic query
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 from datetime import datetimefrom sqlalchemy import create_enginefrom sqlalchemy import Column, String, Integer, DateTimefrom sqlalchemy import or_from sqlalchemy import descfrom sqlalchemy.orm import sessionmakerfrom sqlalchemy.exc import SQLAlchemyErrorfrom sqlalchemy.ext.declarative import declarative_basefrom sqlalchemy.engine.url import URLpostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) Base = declarative_base() class User (Base ): __tablename__ = 'User' id = Column(Integer, primary_key=True ) name = Column(String, nullable=False ) fullname = Column(String, nullable=False ) birth = Column(DateTime) Base.metadata.create_all(bind=engine) users = [ User(name='ed' , fullname='Ed Jones' , birth=datetime(1989 ,7 ,1 )), User(name='wendy' , fullname='Wendy Williams' , birth=datetime(1983 ,4 ,1 )), User(name='mary' , fullname='Mary Contrary' , birth=datetime(1990 ,1 ,30 )), User(name='fred' , fullname='Fred Flinstone' , birth=datetime(1977 ,3 ,12 )), User(name='justin' , fullname="Justin Bieber" )] Session = sessionmaker() Session.configure(bind=engine) session = Session() session.add_all(users) session.commit()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 print ("----> order_by(id):" )query = session.query(User).order_by(User.id ) for _row in query.all (): print (_row.name, _row.fullname, _row.birth) print ("\n----> order_by(desc(id)):" )query = session.query(User).order_by(desc(User.id )) for _row in query.all (): print (_row.name, _row.fullname, _row.birth) print ("\n----> order_by(date):" )query = session.query(User).order_by(User.birth) for _row in query.all (): print (_row.name, _row.fullname, _row.birth) print ("\n----> EQUAL:" )query = session.query(User).filter (User.id == 2 ) _row = query.first() print (_row.name, _row.fullname, _row.birth)print ("\n----> NOT EQUAL:" )query = session.query(User).filter (User.id != 2 ) for _row in query.all (): print (_row.name, _row.fullname, _row.birth) print ("\n----> IN:" )query = session.query(User).filter (User.name.in_(['ed' , 'wendy' ])) for _row in query.all (): print (_row.name, _row.fullname, _row.birth) print ("\n----> NOT IN:" )query = session.query(User).filter (~User.name.in_(['ed' , 'wendy' ])) for _row in query.all (): print (_row.name, _row.fullname, _row.birth) print ("\n----> AND:" )query = session.query(User).filter ( User.name=='ed' , User.fullname=='Ed Jones' ) _row = query.first() print (_row.name, _row.fullname, _row.birth)print ("\n----> OR:" )query = session.query(User).filter ( or_(User.name=='ed' , User.name=='wendy' )) for _row in query.all (): print (_row.name, _row.fullname, _row.birth) print ("\n----> NULL:" )query = session.query(User).filter (User.birth == None ) for _row in query.all (): print (_row.name, _row.fullname) print ("\n----> NOT NULL:" )query = session.query(User).filter (User.birth != None ) for _row in query.all (): print (_row.name, _row.fullname) print ("\n----> LIKE" )query = session.query(User).filter (User.name.like('%ed%' )) for _row in query.all (): print (_row.name, _row.fullname) session.close() engine.dispose()
----> order_by(id):
ed Ed Jones 1989-07-01 00:00:00
wendy Wendy Williams 1983-04-01 00:00:00
mary Mary Contrary 1990-01-30 00:00:00
fred Fred Flinstone 1977-03-12 00:00:00
justin Justin Bieber None
----> order_by(desc(id)):
justin Justin Bieber None
fred Fred Flinstone 1977-03-12 00:00:00
mary Mary Contrary 1990-01-30 00:00:00
wendy Wendy Williams 1983-04-01 00:00:00
ed Ed Jones 1989-07-01 00:00:00
----> order_by(date):
fred Fred Flinstone 1977-03-12 00:00:00
wendy Wendy Williams 1983-04-01 00:00:00
ed Ed Jones 1989-07-01 00:00:00
mary Mary Contrary 1990-01-30 00:00:00
justin Justin Bieber None
----> EQUAL:
wendy Wendy Williams 1983-04-01 00:00:00
----> NOT EQUAL:
ed Ed Jones 1989-07-01 00:00:00
mary Mary Contrary 1990-01-30 00:00:00
fred Fred Flinstone 1977-03-12 00:00:00
justin Justin Bieber None
----> IN:
ed Ed Jones 1989-07-01 00:00:00
wendy Wendy Williams 1983-04-01 00:00:00
----> NOT IN:
mary Mary Contrary 1990-01-30 00:00:00
fred Fred Flinstone 1977-03-12 00:00:00
justin Justin Bieber None
----> AND:
ed Ed Jones 1989-07-01 00:00:00
----> OR:
ed Ed Jones 1989-07-01 00:00:00
wendy Wendy Williams 1983-04-01 00:00:00
----> NULL:
justin Justin Bieber
----> NOT NULL:
ed Ed Jones
wendy Wendy Williams
mary Mary Contrary
fred Fred Flinstone
----> LIKE
ed Ed Jones
fred Fred Flinstone
mapper: Map Table to class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 from sqlalchemy import ( create_engine, Table, MetaData, Column, Integer, String, ForeignKey, inspect) from sqlalchemy.orm import ( mapper, relationship, sessionmaker) postgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) metadata = MetaData(bind=engine) inspector = inspect(engine) metadata.reflect() if 'Address' in inspector.get_table_names(): metadata.tables['Address' ].drop(engine) metadata.remove(metadata.tables['Address' ]) if 'User' in inspector.get_table_names(): metadata.reflect() metadata.tables['User' ].drop(engine) metadata.remove(metadata.tables['User' ]) user = Table('User' , metadata, Column('id' , Integer, primary_key=True ), Column('name' , String), Column('fullname' , String), Column('password' , String)) addr = Table('Address' , metadata, Column('id' , Integer, primary_key=True ), Column('email' , String), Column('user_id' , Integer, ForeignKey('User.id' ))) class User (object ): def __init__ (self, name, fullname, password ): self.name = name self.fullname = fullname self.password = password class Address (object ): def __init__ (self, email ): self.email = email mapper(User, user, properties={ 'addresses' : relationship(Address, backref='user' )}) mapper(Address, addr) metadata.create_all() Session = sessionmaker() Session.configure(bind=engine) session = Session() u = User(name='Hello' , fullname='HelloWorld' , password='ker' ) a = Address(email='[email protected] ' ) u.addresses.append(a) try : session.add(u) session.commit() u = session.query(User).filter (User.name == 'Hello' ).first() print (u.name, u.fullname, u.password) finally : session.close() engine.dispose()
Hello HelloWorld ker
Get table dynamically
使用type()函数创建类对象
使用type()函数时,如果只传入一个参数object,那么将返回该object的类型;
如果分别传入name,bases,dict这三个参数,那么type()函数将会创建一个对象;
使用class定义对象的时候,Python解释器调用type()函数来动态创建对象。
要动态创建一个class对象,type()函数依次传入3个参数:
class的名称,字符串形式;
继承的父类集合,注意Python支持多重继承,如果只有一个父类,注意tuple的单元素写法;
class的方法名称与函数绑定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 from sqlalchemy import ( create_engine, MetaData, Table, inspect, Column, String, Integer) from sqlalchemy.orm import ( mapper, scoped_session, sessionmaker) postgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) metadata = MetaData(bind=engine) class TableTemp (object ): def __init__ (self, name ): self.name = name def get_table (name ): metadata.reflect() if name in metadata.tables: table = metadata.tables[name] else : table = Table(name, metadata, Column('id' , Integer, primary_key=True ), Column('name' , String)) table.create(engine) cls = type (name.title(), (TableTemp,), {}) mapper(cls, table) return cls t = get_table('Hello' ) t = get_table('Hello' ) print (t(name='foo' ))Session = scoped_session(sessionmaker(bind=engine)) try : Session.add(t(name='foo' )) Session.add(t(name='bar' )) Session.commit() for _ in Session.query(t).all (): print (_.name) except Exception as e: Session.rollback() finally : Session.close() engine.dispose()
<__main__.Hello object at 0x000001AEF24AA280>
foo
bar
Object Relational join two tables
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 from sqlalchemy import create_engine, inspectfrom sqlalchemy import Column, Integer, String, ForeignKey, MetaDatafrom sqlalchemy.orm import relationshipfrom sqlalchemy.engine.url import URLfrom sqlalchemy.orm import sessionmakerfrom sqlalchemy.ext.declarative import declarative_baseBase = declarative_base() class User (Base ): __tablename__ = 'user' id = Column(Integer, primary_key=True ) name = Column(String) addresses = relationship("Address" , backref="user" ) class Address (Base ): __tablename__ = 'address' id = Column(Integer, primary_key=True ) email = Column(String) user_id = Column(Integer, ForeignKey('user.id' )) postgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) metadata = MetaData(bind=engine) metadata.reflect() inspector = inspect(engine) if 'address' in inspector.get_table_names(): metadata.tables['address' ].drop(engine) if 'user' in inspector.get_table_names(): metadata.tables['user' ].drop(engine) Base.metadata.create_all(bind=engine) Session = sessionmaker() Session.configure(bind=engine) session = Session() user = User(name='user1' ) mail1 = Address(email='[email protected] ' ) mail2 = Address(email='[email protected] ' ) user.addresses.extend([mail1, mail2]) session.add(user) session.add_all([mail1, mail2]) session.commit() query = session.query(Address, User).join(User) for _a, _u in query.all (): print (_u.name, _a.email) session.close() engine.dispose()
user1 [email protected]
user1 [email protected]
join on relationship and group_by count
关于反向引用 backref
与 back_populates
SQLAlchemy 提供了 backref 和 back_populates 两个参数。两个参数的效果完全一致,区别在于:
backref 只需要在 Parent 类中声明 children,Child.parent 会被动态创建;
back_populates 必须在两个类中显式地使用back_populates
参数,略显繁琐,但是更加清晰。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 from sqlalchemy import ( create_engine, Column, String, Integer, ForeignKey, func) from sqlalchemy.orm import ( relationship, sessionmaker, scoped_session) from sqlalchemy.ext.declarative import declarative_basepostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) metadata = MetaData(bind=engine) Base = declarative_base() class Parent (Base ): __tablename__ = 'parent' id = Column(Integer, primary_key=True ) name = Column(String) children = relationship('Child' , back_populates='parent' ) class Child (Base ): __tablename__ = 'child' id = Column(Integer, primary_key=True ) name = Column(String) parent_id = Column(Integer, ForeignKey('parent.id' )) parent = relationship('Parent' , back_populates='children' ) Base.metadata.create_all(bind=engine) Session = scoped_session(sessionmaker(bind=engine)) p1 = Parent(name="Alice" ) p2 = Parent(name="Bob" ) c1 = Child(name="foo" ) c2 = Child(name="bar" ) c3 = Child(name="ker" ) c4 = Child(name="cat" ) p1.children.extend([c1, c2, c3]) p2.children.append(c4) try : Session.add(p1) Session.add(p2) Session.commit() q = Session.query(Parent, func.count(Child.id ))\ .join(Child)\ .group_by(Parent.id ) for _p, _c in q.all (): print ('parent: {}, num_child: {}' .format (_p.name, _c)) finally : Session.remove() engine.dispose()
parent: Bob, num_child: 1
parent: Alice, num_child: 3
Create tables with dynamic columns (ORM)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 from sqlalchemy import create_enginefrom sqlalchemy import Column, Integer, Stringfrom sqlalchemy import inspectfrom sqlalchemy.engine.url import URLfrom sqlalchemy.ext.declarative import declarative_basepostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) metadata = MetaData(bind=engine) Base = declarative_base() def create_table (name, cols ): Base.metadata.reflect(engine) if name in Base.metadata.tables: return table = type (name, (Base,), cols) table.__table__.create(bind=engine) create_table('Table1' , { '__tablename__' : 'Table1' , 'id' : Column(Integer, primary_key=True ), 'name' : Column(String)}) create_table('Table2' , { '__tablename__' : 'Table2' , 'id' : Column(Integer, primary_key=True ), 'key' : Column(String), 'val' : Column(String)}) inspector = inspect(engine) for _t in inspector.get_table_names(): print (_t) engine.dispose()
EX1
Hello
parent
child
SubExample
email_addr
Test Table
EX2
ex_t
EX3
table1
table2
table3
user
address
User
Address
downtown_a_people
downtown_b_people
Table1
Table2
Close database connection
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 from sqlalchemy import ( create_engine, event, Column, Integer) from sqlalchemy.orm import sessionmakerfrom sqlalchemy.ext.declarative import declarative_basepostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) Base = declarative_base() @event.listens_for(engine, 'engine_disposed' ) def receive_engine_disposed (engine ): print ("engine dispose" ) class Table (Base ): __tablename__ = 'example table' id = Column(Integer, primary_key=True ) Base.metadata.create_all(bind=engine) session = sessionmaker(bind=engine)() try : try : row = Table() session.add(row) session.commit() except Exception as e: session.rollback() raise finally : session.close() finally : engine.dispose()
engine dispose
Warning
Be careful. Close session does not mean close database connection. SQLAlchemy session generally represents the transactions, not connections.
Cannot use the object after close the session
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 from __future__ import print_functionfrom sqlalchemy import ( create_engine, Column, String, Integer) from sqlalchemy.orm import sessionmakerfrom sqlalchemy.ext.declarative import declarative_basepostgres_db = {'drivername' : 'postgres+psycopg2' , 'username' : 'postgres' , 'password' : 'postgres' , 'host' : 'localhost' , 'port' : 5432 , 'database' : 'example' , 'query' : None } db_url = URL(**postgres_db) engine = create_engine(db_url) Base = declarative_base() class Table (Base ): __tablename__ = 'table' id = Column(Integer, primary_key=True ) key = Column(String) val = Column(String) Base.metadata.create_all(bind=engine) session = sessionmaker(bind=engine)() try : t = Table(key="key" , val="val" ) try : print (t.key, t.val) session.add(t) session.commit() except Exception as e: print (e) session.rollback() finally : session.close() print (t.key, t.val) except Exception as e: print ("Cannot use the object after close the session" ) finally : engine.dispose()
key val
Cannot use the object after close the session
小结
里面的很多用法,我自己也还没有用到过,还处在摸索学习的阶段。接下来有这么几个打算:
梳理一下SQLAlchemy中的基本概念,尤其是把数据库本身的跟ORM的理清楚;
对前面提到的这些用法进行归类、整理,弄清其中的一些技巧;
对其中经常用的一些功能,根据自己的需要,再做一下封装。
参考资料
https://www.pythonsheets.com/notes/python-sqlalchemy.html
https://www.cnblogs.com/kirito-c/p/10900024.html
http://einverne.github.io/post/2016/08/sqlalchemy-usage.html#declare-a-mapping
https://docs.sqlalchemy.org/en/13/core/metadata.html
https://stackoverflow.com/questions/41887344/how-to-verify-sqlalchemy-engine-object
https://stackoverflow.com/questions/35918605/how-to-delete-a-table-in-sqlalchemy