SQLAlchemy
一 、字段
类型名 | Python类型 | 说明 |
---|---|---|
Integer | int 普通整数 | 一般是32位 |
SmallInteger | int 取值范围小的整数 | 一般是 16 位 |
BigInteger | int 或 long | 不限制精度的整数 |
Float | float | 浮点数 |
Numeric | decimal.Decimal | 定点数 |
String | str | 变长字符串 |
Text | str | 变长字符串,对较长或不限长度的字符串做了优化 |
Unicode | unicode | 变长 Unicode 字符串 |
UnicodeText | unicode | 对较长或不限长度的字符串做了优化 |
Boolean | bool | 布尔值 |
Date | datetime.date | 日期 |
Time | datetime.time | 时间 |
DateTime | datetime.datetime | 日期和时间 |
Interval | datetime.timedelta | 时间间隔 |
Enum | str | 一 组字符串 |
PickleType | 任何 Python 对象 | 自动使用 Pickle 序列化 |
LargeBinary | str | 二进制文件 |
二、字段约束(column 常用参数)
最常使用的SQLAlchemy列选项,也即约束条件
约束 | 作用 |
---|---|
primary_key: | True设置某个字段为主键。 |
autoincrement: | True设置这个字段为自动增长的。 |
default: | 设置某个字段的默认值。在发表时间这些字段上面经常用。 |
nullable: | 指定某个字段是否为空。默认值是True,就是可以为空。 |
unique: | 指定某个字段的值是否唯一。默认是False。 |
onupdate: | 在数据更新的时候会调用这个参数指定的值或者函数。在第一次插入这条数据的时候,不会用onupdate的值,只会使用default的值。常用于是update_time字段(每次更新数据的时候都要更新该字段值)。 |
index | 如果设为 True,为这列创建索引,提升查询效率 |
doc | 字段说明 |
name: | 指定ORM模型中某个属性映射到表中的字段名。如果不指定,那么会使用这个属性的名字来作为字段名。如果指定了,就会使用指定的这个值作为表字段名。这个参数也可以当作位置参数,在第1个参数来指定。 |
server_default 和 default 的区别
在sqlalchemy 中 定义Column 字段 可以有两个default 相关的字段, 一个是 default
另一个是 server_default
,他们之间的区别呢?
查看源码位置 sqlalchemy.sql.schema.py Column
这个类
-
default
这个属性 ,就是默认生成orm 对象,如果某个字段没有 传值,就使用default 值,然后写入到数据库中。 -
server_default
这个属性,要求是一个str, unicode 类型。 用来生成表结构的时候, 需要指定字段默认值的时候来指定的。
三、SQLAlchemy 默认日期
1. 计算您的数据库中的时间戳,而不是您的客户端
您可能希望拥有由您的数据库服务器计算的所有datetimes
,而不是应用程序服务器。 计算应用程序中的时间戳可能会导致问题,因为networking延迟是可变的,客户端的时钟漂移略有不同,不同的编程语言偶尔计算时间稍有不同。
SQLAlchemy允许你通过传递func.now()
或func.current_timestamp()
(它们是彼此的别名func.current_timestamp()
来实现这一点,它告诉DB自己计算时间戳。
2. 使用SQLALchemy的server_default
对于已经告诉数据库来计算值的default
值,通常使用server_default
而不是default
。 这告诉SQLAlchemy将默认值作为CREATE TABLE
语句的一部分传递。如果您针对此表编写特别脚本,则使用server_default
意味着您不必担心手动将时间戳调用添加到脚本 – 数据库将自动设置它。
3. 了解SQLAlchemy的onupdate
/ server_onupdate
SQLAlchemy也支持onupdate
以便在行更新的任何时候插入一个新的时间戳。最好告诉数据库来计算时间戳本身:
from sqlalchemy.sql import func
time_created = Column(DateTime(timezone=True), server_default=func.now())
time_updated = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
设置
timezone=True
,则表示使用标准UTC时区。
数据库不存储当地时间,是有好处的:
可能面临不同时区的访客,导致前端很难转换时间;
存储UTC标准时间,只需要根据当地时区来进行转换。
有一个server_onupdate
参数,但不像server_default
,它实际上并没有设置任何的服务器端。 它只是告诉SQLalchemy,当更新发生时(也许你在列上build了一个触发器 )你的数据库将会改变列,所以 SQLAlchemy 会询问返回值,以便它可以更新相应的对象。
4. 另外一个潜在的问题是:
如果您在单个事务中进行了一系列更改,则它们都具有相同的时间戳。 这是因为SQL标准指定CURRENT_TIMESTAMP
基于事务的开始返回值。
PostgreSQL提供了在事务内改变的非SQL标准的statement_timestamp()
和clock_timestamp()
。 这里的文档:https://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-CURRENT
5. UTC时间戳
如果您想使用UTC时间戳,则在SQLAlchemy文档中提供了func.utcnow()
的实现的一个存根。 但是,您需要自行提供适当的驱动程序特定function。
你也可以使用sqlalchemy内build函数来设定默认的DateTime
from sqlalchemy.sql import func
DT = Column(DateTime(timezone=True), default=func.now())
应将该default
关键字参数提供给Column对象。
Column(u'timestamp', TIMESTAMP(timezone=True), primary_key=False, nullable=False, default=time_now)
默认值可以是可调用的,在这里我定义如下。
from pytz import timezone from datetime import datetime UTC = timezone('UTC') def time_now(): return datetime.now(UTC)
你可能想要使用onupdate = datetime.now,以便更新也更改last_updated字段。
- 缺省值只在INSERT上设置一次
- onupdate也将该值设置为UPDATE上的可调用 结果。
四、删除单个模型
model_name.__table__.drop(engine)
五、对应模式
relationship 参数
参数 | 作用 |
---|---|
secondary: | 多对多关联类 |
cascade: | 设置级联关系,删除用delete, delete-orphan |
single_parent: | 让级联支持多对多,设置为True 没有此属性会报异常: On X.x, delete-orphan cascade is not supported on a many-to-many or many-to-one relationship when single_parent is not set. Set single_parent=True on the relationship(). |
passive_deletes: | 支持关联(被动)删除,设置为True 没有此属性会报异常:DELETE statement on table ‘B’ expected to delete 1 row(s); Only 0 were matched . |
1). 数据库之SQLAlchemy.relationship方法中的backref
参数
*注意:
-
参数 backref:【反向关联】
-
采用
back_populates
方式 两证表要同时声明;若使用backref
方式在一个表即可。- backref和back_populates: [stackoverflow上对两者的解释]
If you use backref you don’t need to declare the relationship on the second table
就是使用
backref
就不用在两个具有外键的类上都声明relationship
- back_populates 参数赋值参数一定不能是relationship第一个参数的字段,那样相当于被对应关系表中有了重复字段。
-
company是主表,phone是从表。查询phone表,返回phone_obj,可以通过phoen_obj.Company查询到company中外键关联的数据。
查phone表返回company表里的数据。这个称之为:正向查询。
-
company是主表,phone是从表。查询company表,返回company_obj,可以通过company_obj.phone_of_company查询到phone表的外键关联数据。
查company表返回phone表里的数据。这个称之为:反向查询。
2).uselist=False
这个参数是控制查询范围的,如果是一对一我们常把 uselist 设为 False, 默认是 True ,
当我们从 VIP表关联到 VIPInfo表时,如果 uselist为True,那么他会找到对应关联的所有VIPInfo 反之只找一个就结束.所以一对一时我们直接写 False 因为我们知道只有一个对应。
参考官方文档:https://docs.sqlalchemy.org/en/13/orm/basic_relationships.html#one-to-one
3)数据库之SQLAlchemy.relationship方法中的cascade
参数
*注意:
-
只有在数据表一对多情况下使用,不能多对多的使用
-
cascade=‘ ’
,cascade指定为空,如果是提交多表中的数据时,只会添加多表中的数据,不会添加父表数据 -
指定了 relationship 的属性, 没有指定 cascade 参数时,提交一个数据表,相关联的数据也会添加。
将一个数据添加到session中, 和他关联的数据都可以一起存入数据库中。可以通过
relationship
中的关键字参数cascade
设置属性
参数 | 作用 |
---|---|
save-update | 默认参数, 在添加一条数据时, 会将其他和他相关联的数据都添加到数据库中 |
delete | 当删除某一个模型中的数据时,是否也删除使用relationship关联的数据 |
delete-orphan | 表示当对一个ORM对象接触了父表中的关联对象时,自己便会删除掉,并且还需要在子模型类中添加一个参数single_parent=True参数 |
merge | 默认参数, 当在使用session.merge,合并一个对象时,会将使用了relationship相关联的对象进行合并操作 |
expunge | 移除操作时,会将相关联的对象也进行移除, 这个操作只是从session层面的移除, 并不会真正从数据库中删除 |
all | 是对save-update、merge、refresh-expire、expunge、delete |