sqlalchemy中Column的默認值屬性


字段為日期時間類型設置默認值 NULL  :

EntryDate = Column(DateTime,server_default=text('NULL'),nullable=True)

create_time = Column(DateTime, server_default=text('CURRENT_TIMESTAMP'))
update_time = Column(DateTime, server_default=text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'))

文章目錄

 

​ 我們知道 使用 sqlalchemy 定義 ORM 對象,需要給一些 字段設置一個默認值, default 屬性

類似下面的代碼.

  class Person(Base): __tablename__ = 'Person' id = Column(Integer, autoincrement=True, primary_key=True) name = Column(String(length=64), comment='姓名') is_delete = Column(Integer,comment="是否刪除",default=0) def __repr__(self): return "<Person(id='%s', name='%s', mobile='%s')>" % \ (self.id, self.name, self.mobile, ) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

這樣就可以 在 session.add() , session.commit() 的時候,如果沒有提供這個字段的值,就會自動設置會0 寫入到數據庫里面。

我用這個類 創建表的時候 發現, 其實 sqlalchemy 並沒有進行 設置, 表結構里面的默認值。

20201206104137582

通過上面的日志 ,我可以清晰的發現,實際上engine 來執行sql 是上面的建表語句,並沒有將 is_deleted 設置成 默認值。

后來發現 其實 Column 還有一個屬性,叫 server_default 這個值 才是真正可以生成表結構的時候,會設置默認值。

但是 我設置 server_default 值的時候

class Person(Base): __tablename__ = 'Person' id = Column(Integer, autoincrement=True, primary_key=True) name = Column(String(length=64), comment='姓名') # 這里設置 server_default 值 is_deleted = Column(Integer,comment="是否刪除",default=0,server_default=0) def __repr__(self): return "<Person(id='%s', name='%s', mobile='%s')>" % \ (self.id, self.name, self.mobile, ) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

之后生成表結構的時候,發現出現了一個錯誤如下:

Argument ‘arg’ is expected to be one of type '<class ‘str’>'

sqlalchemy.exc.ArgumentError: Argument 'arg' is expected to be one of type '<class 'str'>' or '<class 'sqlalchemy.sql.elements.ClauseElement'>' or '<class 'sqlalchemy.sql.elements.TextClause'>', got '<class 'int'>'

  • 1
  • 2


這里很明顯 說明 參數 錯誤, 我陷入了沉思? 為啥說我參數不對呢?

源碼 sqlalchemy.sql.schema.py 查看 server_default 要求傳入一個字符串類型的變量。

修改 orm 類

from sqlalchemy import Column, Integer, String, text class Person(Base): __tablename__ = 'Person' id = Column(Integer, autoincrement=True, primary_key=True) name = Column(String(length=64), comment='姓名') # 注意這里 只設置 server_default is_deleted = Column(Integer, comment="是否刪除", server_default=text('0')) def __repr__(self): return "<Person(id='%s', name='%s')>" % \ (self.id, self.name) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

執行生成 table 語句 ,發現可以正常生成表結構了,並且default 值 也默認設置好了。


好了,一切看起來 完美了。

所以 如果要想 定義orm ,生成表結構的時候,就自動生成 默認值,一定要使用 server_default 這個 字段,並且要求 這個字段為字符串類型, 可以使用 text 去 裝飾一下。

server_default vs. default 的區別

​ 在sqlalchemy 中 定義Column 字段 可以有兩個default 相關的字段, 一個是 default 另一個是 server_default ,他們之間的區別呢?

查看源碼位置 sqlalchemy.sql.schema.py Column 這個類

default 這個屬性 ,就是默認生成orm 對象,如果某個字段沒有 傳值,就使用default 值,然后寫入到數據庫中。

server_default 這個屬性,要求是一個str, unicode 類型。 用來生成表結構的時候, 需要指定字段默認值的時候來指定的。

看一個小例子

下面以一個例子作為演示,下面我創建一個User 的model 類 , 然后 有一個字段 password 我設置一個 default 的屬性 ,然后創建一個表。

from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, create_engine from sqlalchemy.orm import sessionmaker Base = declarative_base() # 創建連接對象,並使用 pymsql 引擎 conn_str = "mysql+pymysql://{user}:{pwd}@{host}:3306/{db_name}?charset=utf8mb4" connect_info = conn_str.format(user='root', pwd='123456', host='127.0.0.1', db_name='db1') engine = create_engine(connect_info, max_overflow=5) session_factory = sessionmaker() session_factory.configure(bind=engine) session = session_factory() class User(Base): __tablename__ = 'User' id = Column(Integer, autoincrement=True, primary_key=True) name = Column(String(length=64), comment='姓名') mobile = Column(String(length=64), comment='手機號') password = Column(String(length=64), comment='密碼', default='0000') def __repr__(self): return "<User(id='%s', name='%s', mobile='%s', password='%s')>" % \ (self.id, self.name, self.mobile, self.password) def create_table(): # 創建表結構 Base.metadata.create_all(engine) if __name__ == '__main__': create_table() print("create table successfully ") 
  • 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

創建完成后,我們到數據庫查看表結構 ,發現 並沒有 給password 一個默認值。

建表語句 如下:

CREATE TABLE `User` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(64) DEFAULT NULL COMMENT '姓名',
  `mobile` varchar(64) DEFAULT NULL COMMENT '手機號',
  `password` varchar(64) DEFAULT NULL COMMENT '密碼',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

User 表結構中並沒有給 password 生成一個 密碼的default 值。

下面我們使用 sqlalchemy 插入一個 user

if __name__ == '__main__': u = User(name='frank',mobile='123xxxx3456') session.add(u) session.commit() session.close() 
  • 1
  • 2
  • 3
  • 4
  • 5

數據庫查看 沒有任何問題,已經自動把 password 字段 填充成0000了。

這是在執行sql 的時候,當 ORM對象 沒有給某個字段賦值的時候, sqlalchemy 會查看 Column 屬性的default 是否有值,如果有值,則使用 當前值; 如果沒有值,則會默認為default值。

然后在進行執行sql ,所以就自動加上了默認值。

因此想要在表結構生成的時候 就設置默認值, 要使用 server_default 這個屬性,另外server_default的值必須是字符串。

# 正確的設置方式是 is_deleted = Column(Integer, default=0, server_default=text('0')) 
  • 1
  • 2

如果沒有寫server_default參數,那么在代碼中新建對象往數據庫插入的時候是有一個值的,但是在數據庫里查看表結構,會發現表上並沒有給字段設置默認值。

另外server_default的值必須是字符串。

設置表的默認創建時間和更新時間

​ 有的時候我們希望在表創建的時候,有創建 時間和更新時間。 所以 我們就可以使用 server_default 這個屬性 來生成就好了。

from sqlalchemy import TIMESTAMP, Boolean, Column, Float from sqlalchemy.ext.declarative import declarative_base base = declarative_base() class Base(base): __abstract__ = True __table_args__ = { 'mysql_engine': 'InnoDB', 'mysql_charset': 'utf8', 'extend_existing': True } id = Column(INT, primary_key=True, autoincrement=True) create_time = Column(TIMESTAMP, default=None, nullable=True, server_default=text('CURRENT_TIMESTAMP')) update_time = Column(TIMESTAMP, default=None, nullable=True, server_default=text( 'CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP')) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

參考文檔

stackoverflow discussion

官方文檔

readthedocs 地址


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM