前言:该笔记是本人学习SQLAlchemy官方文档整理得来。
查看SQLAlchemy版本
>>> import sqlalchemy
>>> sqlalchemy.__version__
'1.0.15'
>>>
连接数据库
本教程中我们将使用postgresql数据库,连接数据库我们使用create_engine():
>>> >>> from sqlalchemy import create_engine
>>> engine = create_engine('postgresql://ricky:passwd@localhost/my_db', echo=True)
关于SQLAlchemy连接不同的数据库的URL设置,请自行搜索。
echo参数是设置SQLAlchemy日志显示的快捷方式,这样我们在python命令行中执行的命令都会在下面显示出日志信息(这里我们能清楚看到只想的SQL语句详细内容)。如果我们不想看见执行的详细过程,可以将echo
设置为False
。
create_engine()函数返回一个Engin
的实例,代表着访问数据库的接口。
延迟连接
当create_engine()
第一次调用,它没有尝试去连接数据库,仅仅是当我们执行数据库操作时,才会去连接数据库。
定义映射
当我们在使用ORM
的时候,数据库中的一张表对应着我们的一个类,我们使用declarative_base()
创建一个基类。
>>> from sqlalchemy.ext.declarative import declarative_base
>>> Base = declarative_base()
现在我们有了一个基类Base
,我们可以定义很多映射的类,先从一张完整的表格,名字为Users
开始,一个新的User
类将会映射到我们的那种表格上,在类中我们定义关于表格的详细信息。主要是表名、列名和数据类型。
>>> from sqlalchemy import Column, Integer, String
>>> class User(Base):
... __tablename__ = 'users'
...
... id = Column(Integer, primary_key=True)
... name = Column(String)
... fullname = Column(String)
... password = Column(String)
...
... def __repr__(self):
... return "<User(naem=%s, fullname=%s, password=%s)>" % (self.name, self.fullname, self.password)
...
一个最简单的类需要一个__tablename__
属性,和至少一行Column
和一个外键primary key
。
Tip######
User类定义了一个__repr__()
方法,但是这个是可选的,我们在这里定义是为了打印出类的对象的内容。
创建一个模型
通过声明系统,我们已经定义了我们表格的详细信息,我们可以通过__table__
属性来看我们定义的类
>>> User.__table__
Table('users', MetaData(bind=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)
当我们定义了我们的类,声明系统使用一个Python的metaclass
来执行其他任务,一旦这个类声明完成。
表的对象是一个更大的称为元数据集合的一个成员。当我们使用这个系统,可以使用这个对象.metadata
属性声明我们基类的属性。
MetaData是一个注册表,当我们的数据库不存在一个users
表格,我们可以使用MetaData
去创建一个不存在的表格,我们调用MetaData.create_all()
方法,Engine
作为一个数据库的连接。
>>> Base.metadata.create_all(engine)
SELECT ...
PRAGMA table_info("users")
()
CREATE TABLE users (
id INTEGER NOT NULL, name VARCHAR,
fullname VARCHAR,
password VARCHAR,
PRIMARY KEY (id)
)
()
COMMIT
Minimal Table Descriptions vs. Full Descriptions
在上面的声明一个表中的列时,我们注意到列的数据类型为字符串,但是没有指定长度;在SQLite和PostgreSQL中这样的声明是合法的,但是在其他的数据库中是不允许的。所以,如果运行这个教程在洽谈的数据库中,可能会报错。最好我很使用下面的声明方式。
Column(String(50))
另外在Firebird和Oracle数据库中要求sequences去生成一个新的外键约束。你可以使用序列来构造。
from sqlalchemy import Sequence
Column(Integer, Sequence('user_id_seq'), primary_key=True)
完整的Table的定义为:
class User(Base):
__tablename__ = 'users'
id = Column(Integer, Sequence('user_id_seq'), primary_key=True)
name = Column(String(50))
fullname = Column(String(50))
password = Column(String(12))
def __repr__(self):
return "<User(name='%s', fullname='%s', password='%s')>" % (
self.name, self.fullname, self.password)
创建一个映射的类的对象
我们来创建一个User
的对象.
>>> ed_user = User(name='ricky', fullname='yuziyong', password='123')
>>> ed_user.name
'ricky'
>>> ed_user.password
'123'
>>> ed_user.fullname
'yuziyong'
>>> str(ed_user.id)
'None'
尽管我们没有特别在构造函数指定,但是id
属性仍然产生了一个值None,当我们访问它,SQLAlchemy的工具通常会产生一个默认值。