SQLAlchemy 的连接创建是 Lazy 的方式, 即在需要使用时才会去真正创建. 未真正使用之前做的工作, 全是"定义".
连接的定义是在 engine 中做的.
engine 的定义包含了三部分的内容, 一是具体数据库类型的实现, 二是连接池, 三是策略(即 engine 自己的实现).
所谓的数据库类型即是 MYSQL , Postgresql , SQLite 这些不同的数据库.
一般创建 engine 是使用 create_engine
方法:
create_engine('dialect+driver://username:password@host:port/database')
_ENGINE = sqlalchemy.create_engine(FLAGS.sql_connection, **engine_args)
FLAGS.sql_connection为 mysql://root:MYSQL_PASS@192.168.123.177/abc?charset=utf8
engine_args = {
"pool_recycle": FLAGS.sql_idle_timeout,
"echo": False,
'convert_unicode': True,
}
第一个参数:建立数据库连接用的。
create_engine
的调用, 实际上会变成 strategy.create
的调用. 而 strategy 就是 engine 的实现细节. strategy 可以在 create_engine
调用时通过 strategy
参数指定, 目前官方的支持有三种:
mock 这个实现, 会把所有的 SQL 语句的执行交给指定的函数来做, 这个函数是由 create_engine
的 executor
参数指定:
CREATE TABLE [users] (
[id] INTEGER PRIMARY KEY,
[name] TEXT NOT NULL,
[fullname] TEXT NOT NULL,
[password] TEXT NOT NULL
);
描述一张user表
from sqlalchemy import Table, MetaData, Column, Integer, String
metadata = MetaData()
user = Table('users', metadata,
Column('id', Integer, primary_key=True),
Column('name', String(50)),
Column('fullname', String(50)),
Column('password', String(12))
)
user表对应的python类User:
class User(object):
def __init__(self, name, fullname, password):
self.name = name
self.fullname = fullname
self.password = password
定义user表和User类之间的映射关系:
from sqlalchemy.orm import mapper
mapper(User, user)
mapper(python类名,表名)
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
__tablename__ = 'some_table'
id = Column(Integer, primary_key=True)
name = Column(String(50))
# access the mapped Table
SomeClass.__table__
# access the Mapper
SomeClass.__mapper__
from sqlalchemy import Column, Integer, String
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(50))
fullname = Column(String(50))
password = Column(String(12))
def __init__(self, name, fullname, password):
self.name = name
self.fullname = fullname
self.password = password
def __repr__(self):
return "" % (self.name, self.fullname, self.password)
session.execute('create database abc')
print session.execute('show databases').fetchall()
session.execute('use abc')
这里,我使用方法二时,报错,创建了数据库abc,但是,abc中未创建表users。问题不是建表的代码,而是‘use abc’这句有问题,问题没有解决。我使用的方法一。
ed_user = User('ed', 'Ed Jones', 'edspassword')
ed_user = User(name='ed', fullname='Ed Jones', password='foobar')
>>> User.__table__
Table('users', MetaData(None),
Column('id', Integer(), table=<users>, primary_key=True, nullable=False),
Column('name', String(), table=<users>),
Column('fullname', String(), table=<users>),
Column('password', String(), table=<users>), schema=None)
>>> User.__mapper__
<Mapper at 0x...; User>
同样的MetaData可以通过
.metadata
属性找到。
>>> Base.metadata.create_all(engine)
PRAGMA table_info("users")
()
CREATE TABLE users (
id INTEGER NOT NULL,
name VARCHAR,
fullname VARCHAR,
password VARCHAR,
PRIMARY KEY (id)
)
()
COMMIT
Base.metadata.create_all(engine) :创建所有映射类对应的数据库表
Base.metadata.drop_all(engine):删除数据库及表
>>> ed_user = User('ed', 'Ed Jones', 'edspassword')
>>> ed_user.name
'ed'
>>> ed_user.password
'edspassword'
>>> str(ed_user.id)
'None'
为什么
id
这个属性会为
None
值呢?
None
值,在默认情况下,ORM会为所有被映射的表列创建类属性,这些属性是通过Python语言中 描述符(Descriptors)机制来实现的。
id
值为
None
。别着急,稍后当我们介绍将数据持久化后你就可以看到一个新的自动产生的id了。
>>> from sqlalchemy.orm import sessionmaker
>>> Session = sessionmaker(bind=engine)
Session = sessionmaker()
# engine = create_engine(...) 创建引擎
Session.configure(bind=engine,
autocommit=..,
expire_on_commit=..) # 到这里engine应该已经创建
>>> session = Session()
到这里session就获取了由Engine维护的数据库连接池,并且会维持内存中的映射数据直到提交(commit)更改或者关闭会话对象。