API 文件
此文件指定 Peewee 的 API。
資料庫
- class Database(database[, thread_safe=True[, field_types=None[, operations=None[, autoconnect=True[, **kwargs]]]]])
- 參數
database (str) – 資料庫名稱或 SQLite 的檔案名稱 (或
None
來延遲初始化,在這種情況下,您必須呼叫Database.init()
,並指定資料庫名稱)。thread_safe (bool) – 是否將連線狀態儲存在執行緒本地變數中。
field_types (dict) – 要支援的其他欄位類型對應。
operations (dict) – 要支援的其他操作對應。
autoconnect (bool) – 如果嘗試在已關閉的資料庫上執行查詢,是否自動連線到資料庫。
kwargs – 建立連線時將傳遞給資料庫驅動程式的任意關鍵字參數,例如
password
、host
等。
Database
負責執行查詢
管理連線
交易
內省
注意
如果資料庫在執行階段之前未知,則可以使用
None
作為資料庫名稱來實例化資料庫。這樣一來,您可以建立一個資料庫實例,然後在設定已知時在其他地方設定它。這稱為延遲初始化。範例
# Sqlite database using WAL-mode and 32MB page-cache. db = SqliteDatabase('app.db', pragmas={ 'journal_mode': 'wal', 'cache_size': -32 * 1000}) # Postgresql database on remote host. db = PostgresqlDatabase('my_app', user='postgres', host='10.1.0.3', password='secret')
延遲初始化範例
db = PostgresqlDatabase(None) class BaseModel(Model): class Meta: database = db # Read database connection info from env, for example: db_name = os.environ['DATABASE'] db_host = os.environ['PGHOST'] # Initialize database. db.init(db_name, host=db_host, user='postgres')
- param = '?'
字串用作 SQL 查詢中的參數佔位符。
- quote = '"'
用於表示表格或欄位等實體的引號類型。
- init(database[, **kwargs])
- 參數
database (str) – 資料庫名稱或 SQLite 的檔案名稱。
kwargs – 建立連線時將傳遞給資料庫驅動程式的任意關鍵字參數,例如
password
、host
等。
初始化一個延遲資料庫。有關更多資訊,請參閱執行階段資料庫設定。
- connection_context()
建立一個內容管理器,它將在包裝區塊的持續時間內保持連線開啟。
範例
def on_app_startup(): # When app starts up, create the database tables, being sure # the connection is closed upon completion. with database.connection_context(): database.create_tables(APP_MODELS)
- connect([reuse_if_open=False])
- 參數
reuse_if_open (bool) – 如果連線已開啟,則不要引發例外狀況。
- 傳回
是否已開啟新的連線。
- 回傳類型
bool
- 引發
如果連線已開啟且
reuse_if_open
未設定為True
,則引發OperationalError
。
開啟與資料庫的連線。
- close()
- 傳回
是否已關閉連線。如果資料庫已關閉,則此傳回
False
。- 回傳類型
bool
關閉與資料庫的連線。
- is_closed()
- 傳回
如果資料庫已關閉,則傳回
True
,如果開啟,則傳回False
。- 回傳類型
bool
- connection()
傳回開啟的連線。如果連線未開啟,則會開啟一個連線。連線將是底層資料庫驅動程式用來封裝資料庫連線的任何內容。
- cursor([named_cursor=None])
- 參數
named_cursor – 供內部使用。
傳回目前連線上的
cursor
物件。如果連線未開啟,則會開啟一個連線。游標將是底層資料庫驅動程式用來封裝資料庫游標的任何內容。
- execute_sql(sql[, params=None])
- 參數
sql (str) – 要執行的 SQL 字串。
params (tuple) – 查詢的參數。
- 傳回
游標物件。
執行 SQL 查詢並傳回結果的游標。
- execute(query[, **context_options])
- 參數
query –
Query
實例。context_options – 要傳遞給 SQL 產生器的任意選項。
- 傳回
游標物件。
透過編譯
Query
實例並執行產生的 SQL 來執行 SQL 查詢。
- last_insert_id(cursor[, query_type=None])
- 參數
cursor – 游標物件。
- 傳回
最後插入的列的主鍵。
- rows_affected(cursor)
- 參數
cursor – 游標物件。
- 傳回
查詢修改的列數。
- in_transaction()
- 傳回
目前是否開啟交易。
- 回傳類型
bool
- atomic([...])
建立一個內容管理器,它會在交易中 (或如果區塊是巢狀的,則為儲存點) 執行包裝區塊中的任何查詢。
可以巢狀呼叫
atomic()
。atomic()
也可以用作裝飾器。特定於資料庫的參數
PostgresqlDatabase
和MySQLDatabase
接受isolation_level
參數。SqliteDatabase
接受lock_type
參數。- 參數
isolation_level (str) – 隔離策略:SERIALIZABLE、READ COMMITTED、REPEATABLE READ、READ UNCOMMITTED
lock_type (str) – 鎖定策略:DEFERRED、IMMEDIATE、EXCLUSIVE。
範例程式碼
with db.atomic() as txn: perform_operation() with db.atomic() as nested_txn: perform_another_operation()
交易和儲存點可以在包裝區塊內明確提交或回滾。如果發生這種情況,則在提交/回滾後開始新的交易或儲存點。
範例
with db.atomic() as txn: User.create(username='mickey') txn.commit() # Changes are saved and a new transaction begins. User.create(username='huey') txn.rollback() # "huey" will not be saved. User.create(username='zaizee') # Print the usernames of all users. print([u.username for u in User.select()]) # Prints ["mickey", "zaizee"]
- manual_commit()
建立一個內容管理器,它會在包裝區塊的持續時間內停用所有交易管理。
範例
with db.manual_commit(): db.begin() # Begin transaction explicitly. try: user.delete_instance(recursive=True) except: db.rollback() # Rollback -- an error occurred. raise else: try: db.commit() # Attempt to commit changes. except: db.rollback() # Error committing, rollback. raise
上面的程式碼等同於以下程式碼
with db.atomic(): user.delete_instance(recursive=True)
- session_start()
開始新的交易 (不使用內容管理器或裝飾器)。如果您打算在交易內執行一系列操作,但使用裝飾器或內容管理器不合適,則此方法很有用。
注意
強烈建議您盡可能使用
Database.atomic()
方法來管理交易/儲存點。atomic
方法會正確管理巢狀,使用適當的結構 (例如,交易與儲存點),並始終在自身之後清理。只有在操作序列不易於使用內容管理器或裝飾器包裝時,才應使用
session_start()
方法。警告
您在呼叫
session_start
方法後,必須始終呼叫session_commit()
或session_rollback()
。
- session_commit()
提交使用
session_start()
開始的事務期間所做的任何變更。
- session_rollback()
回滾使用
session_start()
開始的事務期間所做的任何變更。
- transaction([...])
建立一個上下文管理器,在事務中運行包裝區塊中的所有查詢。
特定於資料庫的參數
PostgresqlDatabase
和MySQLDatabase
接受isolation_level
參數。SqliteDatabase
接受lock_type
參數。- 參數
isolation_level (str) – 隔離策略:SERIALIZABLE、READ COMMITTED、REPEATABLE READ、READ UNCOMMITTED
lock_type (str) – 鎖定策略:DEFERRED、IMMEDIATE、EXCLUSIVE。
警告
不能巢狀呼叫
transaction
。只有最上層的呼叫才會生效。回滾或提交巢狀事務上下文管理器具有未定義的行為。
- savepoint()
建立一個上下文管理器,在儲存點中運行包裝區塊中的所有查詢。儲存點可以任意巢狀。
警告
呼叫
savepoint
必須在事務內發生。
- begin()
在使用手動提交模式時開始事務。
注意
此方法應僅與
manual_commit()
上下文管理器結合使用。
- commit()
手動提交目前活動的事務。
注意
此方法應僅與
manual_commit()
上下文管理器結合使用。
- rollback()
手動回滾目前活動的事務。
注意
此方法應僅與
manual_commit()
上下文管理器結合使用。
- batch_commit(it, n)
- 參數
it (iterable) – 一個可迭代物件,其項目將被產生 (yield)。
n (int) – 每 n 個項目提交一次。
- 傳回
一個與提供的可迭代物件等效的可迭代物件,此外,每 n 個項目會在一項事務中產生。
此方法的目的是簡化大型操作的批次處理,例如插入、更新等。您傳遞一個可迭代物件和每個批次的項目數,這些項目將由一個等效的迭代器返回,該迭代器將每個批次包裝在事務中。
範例
# Some list or iterable containing data to insert. row_data = [{'username': 'u1'}, {'username': 'u2'}, ...] # Insert all data, committing every 100 rows. If, for example, # there are 789 items in the list, then there will be a total of # 8 transactions (7x100 and 1x89). for row in db.batch_commit(row_data, 100): User.create(**row)
一個可能更有效率的替代方案是將資料批次處理到一個多值
INSERT
陳述式中(例如,使用Model.insert_many()
)。with db.atomic(): for idx in range(0, len(row_data), 100): # Insert 100 rows at a time. rows = row_data[idx:idx + 100] User.insert_many(rows).execute()
- table_exists(table[, schema=None])
- 參數
table (str) – 資料表名稱。
schema (str) – 綱要名稱(選用)。
- 傳回
bool
指示資料表是否存在。
- get_tables([schema=None])
- 參數
schema (str) – 綱要名稱(選用)。
- 傳回
資料庫中資料表名稱的清單。
- get_indexes(table[, schema=None])
- 參數
table (str) – 資料表名稱。
schema (str) – 綱要名稱(選用)。
傳回
IndexMetadata
元組的清單。範例
print(db.get_indexes('entry')) [IndexMetadata( name='entry_public_list', sql='CREATE INDEX "entry_public_list" ...', columns=['timestamp'], unique=False, table='entry'), IndexMetadata( name='entry_slug', sql='CREATE UNIQUE INDEX "entry_slug" ON "entry" ("slug")', columns=['slug'], unique=True, table='entry')]
- get_columns(table[, schema=None])
- 參數
table (str) – 資料表名稱。
schema (str) – 綱要名稱(選用)。
傳回
ColumnMetadata
元組的清單。範例
print(db.get_columns('entry')) [ColumnMetadata( name='id', data_type='INTEGER', null=False, primary_key=True, table='entry'), ColumnMetadata( name='title', data_type='TEXT', null=False, primary_key=False, table='entry'), ...]
- get_primary_keys(table[, schema=None])
- 參數
table (str) – 資料表名稱。
schema (str) – 綱要名稱(選用)。
傳回構成主鍵的欄名稱的清單。
範例
print(db.get_primary_keys('entry')) ['id']
- get_foreign_keys(table[, schema=None])
- 參數
table (str) – 資料表名稱。
schema (str) – 綱要名稱(選用)。
傳回資料表上存在的鍵的
ForeignKeyMetadata
元組的清單。範例
print(db.get_foreign_keys('entrytag')) [ForeignKeyMetadata( column='entry_id', dest_table='entry', dest_column='id', table='entrytag'), ...]
- get_views([schema=None])
- 參數
schema (str) – 綱要名稱(選用)。
傳回資料庫中存在的 VIEW 的
ViewMetadata
元組的清單。範例
print(db.get_views()) [ViewMetadata( name='entries_public', sql='CREATE VIEW entries_public AS SELECT ... '), ...]
- sequence_exists(seq)
- 參數
seq (str) – 序列的名稱。
- 傳回
序列是否存在。
- 回傳類型
bool
- create_tables(models[, **options])
- 參數
models (list) –
Model
類別的清單。options – 呼叫
Model.create_table()
時要指定的選項。
為給定的模型清單建立資料表、索引和相關聯的中繼資料。
相依性會被解析,以便依適當的順序建立資料表。
- drop_tables(models[, **options])
- 參數
models (list) –
Model
類別的清單。kwargs – 呼叫
Model.drop_table()
時要指定的選項。
為給定的模型清單捨棄資料表、索引和相關聯的中繼資料。
相依性會被解析,以便依適當的順序捨棄資料表。
- bind(models[, bind_refs=True[, bind_backrefs=True]])
- 參數
models (list) – 一個或多個要繫結的
Model
類別。bind_refs (bool) – 繫結相關的模型。
bind_backrefs (bool) – 繫結反向參照的相關模型。
將給定的模型清單和指定的關係繫結到資料庫。
- bind_ctx(models[, bind_refs=True[, bind_backrefs=True]])
- 參數
models (list) – 要繫結到資料庫的模型清單。
bind_refs (bool) – 繫結使用外鍵參照的模型。
bind_backrefs (bool) – 繫結使用外鍵參照給定模型的模型。
建立一個上下文管理器,在包裝區塊的持續時間內,將給定的模型繫結(關聯)到目前的資料庫。
範例
MODELS = (User, Account, Note) # Bind the given models to the db for the duration of wrapped block. def use_test_database(fn): @wraps(fn) def inner(self): with test_db.bind_ctx(MODELS): test_db.create_tables(MODELS) try: fn(self) finally: test_db.drop_tables(MODELS) return inner class TestSomething(TestCase): @use_test_database def test_something(self): # ... models are bound to test database ... pass
- extract_date(date_part, date_field)
- 參數
date_part (str) – 要提取的日期部分,例如「year」。
date_field (Node) – 包含日期/時間的 SQL 節點,例如
DateTimeField
。
- 傳回
代表函數呼叫的 SQL 節點,該函數呼叫將傳回提供的日期部分。
提供一個相容的介面來提取日期時間的一部分。
- truncate_date(date_part, date_field)
- 參數
date_part (str) – 要截斷到的日期部分,例如「day」。
date_field (Node) – 包含日期/時間的 SQL 節點,例如
DateTimeField
。
- 傳回
代表函數呼叫的 SQL 節點,該函數呼叫將傳回截斷的日期部分。
提供一個相容的介面,用於將日期時間截斷到給定的解析度。
- random()
- 傳回
代表函數呼叫的 SQL 節點,該函數呼叫將傳回隨機值。
一個相容的介面,用於呼叫資料庫提供的適當的隨機數產生函數。對於 Postgres 和 Sqlite,這相當於
fn.random()
,對於 MySQL 則為fn.rand()
。
- class SqliteDatabase(database[, pragmas=None[, timeout=5[, returning_clause=None[, **kwargs]]]])
- 參數
pragmas – 一個字典或一個包含 pragma 鍵值對的 2 元組列表,用於在每次開啟連線時設定。
timeout – 設定 SQLite 驅動程式的忙碌逾時時間(以秒為單位)。
returning_clause (bool) – 自動對大量 INSERT 查詢使用 RETURNING 子句(需要 Sqlite 3.35 或更新版本)。
Sqlite 資料庫實作。
SqliteDatabase
提供一些僅由 Sqlite 提供的進階功能。註冊自訂的彙總函數、校對函數和一般函數
載入 C 擴充功能
進階事務(指定鎖定類型)
如需更多功能,請參閱
SqliteExtDatabase
。
初始化資料庫並設定一些 PRAGMA 的範例
db = SqliteDatabase('my_app.db', pragmas=( ('cache_size', -16000), # 16MB ('journal_mode', 'wal'), # Use write-ahead-log journal mode. )) # Alternatively, pragmas can be specified using a dictionary. db = SqliteDatabase('my_app.db', pragmas={'journal_mode': 'wal'})
- pragma(key[, value=SENTINEL[, permanent=False]])
- 參數
key – 設定名稱。
value – 設定的新值(可選)。
permanent – 在每次開啟連線時套用此 pragma。
在活動連線上執行一次 PRAGMA 查詢。如果未指定值,則會傳回目前的值。
如果指定
permanent
,則每次開啟新連線時也會執行 PRAGMA 查詢,以確保它始終有效。注意
預設情況下,這僅影響目前的連線。如果執行的 PRAGMA 不是持久的,則必須指定
permanent=True
以確保在後續連線上設定 pragma。
- cache_size
取得或設定目前連線的 cache_size pragma。
- foreign_keys
取得或設定目前連線的 foreign_keys pragma。
- journal_mode
取得或設定 journal_mode pragma。
- journal_size_limit
取得或設定 journal_size_limit pragma。
- mmap_size
取得或設定目前連線的 mmap_size pragma。
- page_size
取得或設定 page_size pragma。
- read_uncommitted
取得或設定目前連線的 read_uncommitted pragma。
- synchronous
取得或設定目前連線的 synchronous pragma。
- wal_autocheckpoint
取得或設定目前連線的 wal_autocheckpoint pragma。
- timeout
取得或設定忙碌逾時時間(秒)。
- register_aggregate(klass[, name=None[, num_params=-1]])
- 參數
klass – 實作彙總 API 的類別。
name (str) – 彙總函數名稱(預設為類別名稱)。
num_params (int) – 彙總函數接受的參數數量,或 -1 表示接受任意數量。
註冊使用者定義的彙總函數。
每次開啟新連線時,都會註冊該函數。此外,如果連線已開啟,也會向開啟的連線註冊彙總函數。
- aggregate([name=None[, num_params=-1]])
- 參數
name (str) – 彙總函數的名稱(預設為類別名稱)。
num_params (int) – 彙總函數接受的參數數量,或 -1 表示接受任意數量。
用於註冊使用者定義的彙總函數的類別裝飾器。
範例
@db.aggregate('md5') class MD5(object): def initialize(self): self.md5 = hashlib.md5() def step(self, value): self.md5.update(value) def finalize(self): return self.md5.hexdigest() @db.aggregate() class Product(object): '''Like SUM() except calculates cumulative product.''' def __init__(self): self.product = 1 def step(self, value): self.product *= value def finalize(self): return self.product
- register_collation(fn[, name=None])
- 參數
fn – 校對函數。
name (str) – 校對函數的名稱(預設為函數名稱)
註冊使用者定義的校對函數。每次開啟新連線時,都會註冊該校對函數。此外,如果連線已開啟,也會向開啟的連線註冊校對函數。
- collation([name=None])
- 參數
name (str) – 校對函數的名稱(預設為函數名稱)
用於註冊使用者定義的校對函數的裝飾器。
範例
@db.collation('reverse') def collate_reverse(s1, s2): return -cmp(s1, s2) # Usage: Book.select().order_by(collate_reverse.collation(Book.title)) # Equivalent: Book.select().order_by(Book.title.asc(collation='reverse'))
您可能已經注意到,原始的
collate_reverse
函數有一個名為collation
的特殊屬性。此額外屬性提供了一種簡寫方式來產生使用自訂校對函數所需的 SQL。
- register_function(fn[, name=None[, num_params=-1[, deterministic=None]]])
- 參數
fn – 使用者定義的純量函數。
name (str) – 函數的名稱(預設為函數名稱)
num_params (int) – 函數接受的參數數量,或 -1 表示接受任意數量。
deterministic (bool) – 函數對於給定的輸入是否為確定性的(這是在索引中使用該函數所必需的)。需要 Sqlite 3.20 或更新版本,以及
sqlite3
驅動程式支援(在 Python 3.8 中新增至 stdlib)。
註冊使用者定義的純量函數。每次開啟新連線時,都會註冊該函數。此外,如果連線已開啟,也會向開啟的連線註冊函數。
- func([name=None[, num_params=-1[, deterministic=None]]])
- 參數
name (str) – 函數的名稱(預設為函數名稱)。
num_params (int) – 函數接受的參數數量,或 -1 表示接受任意數量。
deterministic (bool) – 函數對於給定的輸入是否為確定性的(這是在索引中使用該函數所必需的)。需要 Sqlite 3.20 或更新版本,以及
sqlite3
驅動程式支援(在 Python 3.8 中新增至 stdlib)。
用於註冊使用者定義的純量函數的裝飾器。
範例
@db.func('title_case') def title_case(s): return s.title() if s else '' # Usage: title_case_books = Book.select(fn.title_case(Book.title))
- register_window_function(klass[, name=None[, num_params=-1]])
- 參數
klass – 實作視窗函數 API 的類別。
name (str) – 視窗函數名稱(預設為類別名稱)。
num_params (int) – 函數接受的參數數量,或 -1 表示接受任意數量。
註冊使用者定義的視窗函數。
注意
此功能需要 SQLite >= 3.25.0 以及 pysqlite3 >= 0.2.0。
每次開啟新連線時,都會註冊視窗函數。此外,如果連線已開啟,也會向開啟的連線註冊視窗函數。
- window_function([name=None[, num_params=-1]])
- 參數
name (str) – 視窗函數的名稱(預設為類別名稱)。
num_params (int) – 函數接受的參數數量,或 -1 表示接受任意數量。
用於註冊使用者定義的視窗函數的類別裝飾器。視窗函數必須定義下列方法
step(<params>)
- 接收來自一列的值並更新狀態。inverse(<params>)
- 給定值的step()
的反向操作。value()
- 傳回視窗函數的目前值。finalize()
- 傳回視窗函數的最終值。
範例
@db.window_function('my_sum') class MySum(object): def __init__(self): self._value = 0 def step(self, value): self._value += value def inverse(self, value): self._value -= value def value(self): return self._value def finalize(self): return self._value
- table_function([name=None])
用於註冊
TableFunction
的類別裝飾器。資料表函數是使用者定義的函數,它可以傳回任何數量的表格資料列,而不是傳回單個純量值。範例
from playhouse.sqlite_ext import TableFunction @db.table_function('series') class Series(TableFunction): columns = ['value'] params = ['start', 'stop', 'step'] def initialize(self, start=0, stop=None, step=1): """ Table-functions declare an initialize() method, which is called with whatever arguments the user has called the function with. """ self.start = self.current = start self.stop = stop or float('Inf') self.step = step def iterate(self, idx): """ Iterate is called repeatedly by the SQLite database engine until the required number of rows has been read **or** the function raises a `StopIteration` signalling no more rows are available. """ if self.current > self.stop: raise StopIteration ret, self.current = self.current, self.current + self.step return (ret,) # Usage: cursor = db.execute_sql('SELECT * FROM series(?, ?, ?)', (0, 5, 2)) for value, in cursor: print(value) # Prints: # 0 # 2 # 4
- unregister_aggregate(name)
- 參數
name – 使用者定義的彙總函數名稱。
取消註冊使用者定義的彙總函數。
- unregister_collation(name)
- 參數
name – 使用者定義的定序名稱。
取消註冊使用者定義的定序。
- unregister_function(name)
- 參數
name – 使用者定義的純量函數名稱。
取消註冊使用者定義的純量函數。
- unregister_table_function(name)
- 參數
name – 使用者定義的資料表函數名稱。
- 傳回
True 或 False,取決於函數是否已移除。
取消註冊使用者定義的純量函數。
- load_extension(extension_module)
載入給定的 C 擴充功能。如果呼叫執行緒中目前有開啟連線,則該擴充功能將會載入到該連線以及所有後續連線。
例如,如果您已編譯閉包表擴充功能並希望在您的應用程式中使用它,您可以寫入
db = SqliteExtDatabase('my_app.db') db.load_extension('closure')
- attach(filename, name)
- 參數
filename (str) – 要附加的資料庫(或
:memory:
以用於記憶體中)name (str) – 已附加資料庫的綱要名稱。
- 傳回
表示成功的布林值
註冊另一個將附加到每個資料庫連線的資料庫檔案。如果主要資料庫目前已連線,則新的資料庫將會附加到開啟的連線上。
注意
使用此方法附加的資料庫將會在每次開啟資料庫連線時附加。
- detach(name)
- 參數
name (str) – 已附加資料庫的綱要名稱。
- 傳回
表示成功的布林值
取消註冊先前呼叫
attach()
所附加的另一個資料庫檔案。如果主要資料庫目前已連線,則附加的資料庫將會從開啟的連線中分離。
- atomic([lock_type=None])
- 參數
lock_type (str) – 鎖定策略:DEFERRED、IMMEDIATE、EXCLUSIVE。
建立原子上下文管理器,可選擇使用指定的鎖定策略(如果未指定,則會使用 DEFERRED)。
注意
鎖定類型僅適用於最外層的
atomic()
區塊。
- transaction([lock_type=None])
- 參數
lock_type (str) – 鎖定策略:DEFERRED、IMMEDIATE、EXCLUSIVE。
建立使用指定鎖定策略的交易上下文管理器(預設為 DEFERRED)。
- class PostgresqlDatabase(database[, register_unicode=True[, encoding=None[, isolation_level=None]]])
Postgresql 資料庫實作。
其他可選的關鍵字參數
- 參數
register_unicode (bool) – 註冊 Unicode 類型。
encoding (str) – 資料庫編碼。
isolation_level (int) – 隔離等級常數,定義於
psycopg2.extensions
模組中。
- set_time_zone(timezone)
- 參數
timezone (str) – 時區名稱,例如「US/Central」。
- 傳回
沒有傳回值。
在目前連線上設定時區。如果沒有開啟連線,則會開啟一個連線。
- atomic([isolation_level=None])
- 參數
isolation_level (str) – 隔離策略:SERIALIZABLE、READ COMMITTED、REPEATABLE READ、READ UNCOMMITTED
建立原子上下文管理器,可選擇使用指定的隔離等級(如果未指定,則會使用伺服器預設值)。
注意
隔離等級僅適用於最外層的
atomic()
區塊。
- transaction([isolation_level=None])
- 參數
isolation_level (str) – 隔離策略:SERIALIZABLE、READ COMMITTED、REPEATABLE READ、READ UNCOMMITTED
建立交易上下文管理器,可選擇使用指定的隔離等級(如果未指定,則會使用伺服器預設值)。
- class MySQLDatabase(database[, **kwargs])
MySQL 資料庫實作。
- atomic([isolation_level=None])
- 參數
isolation_level (str) – 隔離策略:SERIALIZABLE、READ COMMITTED、REPEATABLE READ、READ UNCOMMITTED
建立原子上下文管理器,可選擇使用指定的隔離等級(如果未指定,則會使用伺服器預設值)。
注意
隔離等級僅適用於最外層的
atomic()
區塊。
- transaction([isolation_level=None])
- 參數
isolation_level (str) – 隔離策略:SERIALIZABLE、READ COMMITTED、REPEATABLE READ、READ UNCOMMITTED
建立交易上下文管理器,可選擇使用指定的隔離等級(如果未指定,則會使用伺服器預設值)。
查詢產生器
- class Node
組成 SQL 查詢的 AST 的所有元件的基礎類別。
- static copy(method)
與會改變節點狀態的 Node 方法搭配使用的裝飾器。這允許方法鏈結,例如
query = MyModel.select() new_query = query.where(MyModel.field == 'value')
- unwrap()
用於遞迴解開「已包裝」節點的 API。基本案例是傳回 self。
- is_alias()
用於判斷節點在任何時候是否已被使用者明確別名的 API。
- class Source([alias=None])
列元組的來源,例如資料表、聯結或選取查詢。預設會提供名為「c」的「magic」屬性,該屬性是資料行/屬性查閱的工廠,例如
User = Table('users') query = (User .select(User.c.username) .where(User.c.active == True) .order_by(User.c.username))
- alias(name)
傳回已套用給定別名的物件複本。
- select(*columns)
- 參數
columns –
Column
實例、運算式、函數、子查詢或您想要選取的任何其他項目。
在資料表上建立
Select
查詢。如果資料表明確宣告資料行且未提供任何資料行,則預設會選取資料表定義的所有資料行。
- join(dest[, join_type='INNER'[, on=None]])
-
聯結類型可以是下列其中之一
JOIN.INNER
JOIN.LEFT_OUTER
JOIN.RIGHT_OUTER
JOIN.FULL
JOIN.FULL_OUTER
JOIN.CROSS
- class BaseTable
類表格物件的基礎類別,支援透過運算子多載進行 JOIN。
- __and__(dest)
對
dest
執行 INNER join。
- __add__(dest)
對
dest
執行 LEFT OUTER join。
- __sub__(dest)
對
dest
執行 RIGHT OUTER join。
- __or__(dest)
對
dest
執行 FULL OUTER join。
- __mul__(dest)
對
dest
執行 CROSS join。
- class Table(name[, columns=None[, primary_key=None[, schema=None[, alias=None]]]])
表示資料庫中的表格 (或類似表格的物件,例如視圖)。
- 參數
name (str) – 資料庫表格名稱
columns (tuple) – 欄位名稱清單 (選用)。
primary_key (str) – 主鍵欄位的名稱。
schema (str) – 用於存取表格的綱要名稱 (如果需要)。
alias (str) – 在 SQL 查詢中使用的表格別名。
注意
如果指定了欄位,則魔術「c」屬性將被停用。
當未明確定義欄位時,表格會具有一個特殊的屬性「c」,它是一個工廠,可動態提供對表格欄位的存取。
範例
User = Table('users') query = (User .select(User.c.id, User.c.username) .order_by(User.c.username))
當 有 指定欄位時的等效範例
User = Table('users', ('id', 'username')) query = (User .select(User.id, User.username) .order_by(User.username))
- bind([database=None])
- 參數
database –
Database
物件。
將此表格繫結至指定的資料庫 (或透過留空來取消繫結)。
當表格繫結到資料庫時,可以對其執行查詢,而無需在查詢的 execute 方法中指定資料庫。
- select(*columns)
- 參數
columns –
Column
實例、運算式、函數、子查詢或您想要選取的任何其他項目。
在資料表上建立
Select
查詢。如果資料表明確宣告資料行且未提供任何資料行,則預設會選取資料表定義的所有資料行。範例
User = Table('users', ('id', 'username')) # Because columns were defined on the Table, we will default to # selecting both of the User table's columns. # Evaluates to SELECT id, username FROM users query = User.select() Note = Table('notes') query = (Note .select(Note.c.content, Note.c.timestamp, User.username) .join(User, on=(Note.c.user_id == User.id)) .where(Note.c.is_published == True) .order_by(Note.c.timestamp.desc())) # Using a function to select users and the number of notes they # have authored. query = (User .select( User.username, fn.COUNT(Note.c.id).alias('n_notes')) .join( Note, JOIN.LEFT_OUTER, on=(User.id == Note.c.user_id)) .order_by(fn.COUNT(Note.c.id).desc()))
- insert([insert=None[, columns=None[, **kwargs]]])
- 參數
insert – 一個將欄位對應至值的字典,一個產生字典的可迭代物件 (即清單),或是一個
Select
查詢。columns (list) – 當要插入的資料不是字典時,要插入的欄位清單。
kwargs – 欄位名稱對應至值的對應。
建立一個進入表格的
Insert
查詢。
- class Join(lhs, rhs[, join_type=JOIN.INNER[, on=None[, alias=None]]])
表示兩個類似表格物件之間的 JOIN。
- 參數
lhs – JOIN 的左側。
rhs – JOIN 的右側。
join_type – JOIN 的類型。例如 JOIN.INNER、JOIN.LEFT_OUTER 等。
on – 描述 JOIN 謂詞的運算式。
alias (str) – 要套用至已 JOIN 資料的別名。
- on(predicate)
- 參數
predicate (Expression) – JOIN 謂詞。
指定用於此 JOIN 的謂詞運算式。
- class ValuesList(values[, columns=None[, alias=None]])
表示一個可以像表格一樣使用的值清單。
- 參數
values – 一個包含要表示的列資料的清單-清單。
columns (list) – 要給予每列中欄位的名稱。
alias (str) – 要用於值清單的別名。
範例
data = [(1, 'first'), (2, 'second')] vl = ValuesList(data, columns=('idx', 'name')) query = (vl .select(vl.c.idx, vl.c.name) .order_by(vl.c.idx)) # Yields: # SELECT t1.idx, t1.name # FROM (VALUES (1, 'first'), (2, 'second')) AS t1(idx, name) # ORDER BY t1.idx
- columns(*names)
- 參數
names – 要套用至資料欄位的名稱。
範例
vl = ValuesList([(1, 'first'), (2, 'second')]) vl = vl.columns('idx', 'name').alias('v') query = vl.select(vl.c.idx, vl.c.name) # Yields: # SELECT v.idx, v.name # FROM (VALUES (1, 'first'), (2, 'second')) AS v(idx, name)
- class CTE(name, query[, recursive=False[, columns=None]])
表示一個通用表格運算式。如需範例查詢,請參閱 通用表格運算式。
- 參數
name – CTE 的名稱。
query – 描述 CTE 的
Select
查詢。recursive (bool) – CTE 是否為遞迴。
columns (list) – CTE 產生的欄位的明確清單 (選用)。
- class ColumnBase
類別型物件、屬性或表達式的基底類別。
類別型物件可以使用各種運算符號和特殊方法組合。
&
:邏輯 AND|
:邏輯 OR+
:加法-
:減法*
:乘法/
:除法^
:互斥或==
:等於!=
:不等於>
:大於<
:小於>=
:大於等於<=
:小於等於<<
:IN
>>
:IS
(例如IS NULL
)%
:LIKE
**
:ILIKE
bin_and()
:二進制 ANDbin_or()
:二進制 ORin_()
:IN
not_in()
:NOT IN
regexp()
:REGEXP
is_null(True/False)
:IS NULL
或IS NOT NULL
contains(s)
:LIKE %s%
startswith(s)
:LIKE s%
endswith(s)
:LIKE %s
between(low, high)
:BETWEEN low AND high
concat()
:||
- asc([collation=None[, nulls=None]])
- 參數
collation (str) – 用於排序的校對名稱。
nulls (str) – 排序空值 (FIRST 或 LAST)。
- 傳回
欄位的遞增
Ordering
物件。
- class Negated(node)
表示一個取反的類別型物件。
- class Value(value[, converterNone[, unpack=True]])
- 參數
value – Python 物件或純量值。
converter – 用於將值轉換成資料庫可理解的型別的函式。
unpack (bool) – 是否應該將清單或元組解包成值清單或視為原樣。
要用於參數化查詢的值。呼叫者有責任確保傳入的值可以適應資料庫驅動程式可理解的型別。
- AsIs(value)
表示一個被視為原樣並直接傳回給資料庫驅動程式的
Value
。如果您正在使用接受原生 Python 資料型別的資料庫擴充功能,並且不希望 Peewee 對值施加任何處理,這可能很有用。
- class Cast(node, cast)
- 參數
node – 類別型物件。
cast (str) – 要轉換成的型別。
表示
CAST(<node> AS <cast>)
表達式。
- class Ordering(node, direction[, collation=None[, nulls=None]])
- 參數
node – 類別型物件。
direction (str) – ASC 或 DESC
collation (str) – 用於排序的校對名稱。
nulls (str) – 排序空值 (FIRST 或 LAST)。
表示依類別型物件排序。
Postgresql 支援非標準子句(“NULLS FIRST/LAST”)。對於不支援此項目的資料庫(Sqlite / MySQL),Peewee 將自動使用等效的
CASE
陳述式。- collate([collation=None])
- 參數
collation (str) – 用於排序的校對名稱。
- class Expression(lhs, op, rhs[, flat=True])
- 參數
lhs – 左側運算元。
op – 運算符。
rhs – 右側運算元。
flat (bool) – 是否將表達式包在括號中。
表示 (lhs op rhs) 形式的二元表達式,例如 (foo + 1)。
- class Entity(*path)
- 參數
path – 組成實體名稱的點分隔路徑的各個部分。
表示查詢中帶引號的實體,例如表格、欄位、別名。名稱可能包含多個部分,例如 “a_table”.”column_name”。
- __getattr__(self, attr)
用於建立子實體的工廠方法。
- class SQL(sql[, params=None])
- 參數
sql (str) – SQL 查詢字串。
params (tuple) – 查詢的參數 (可選)。
表示參數化的 SQL 查詢或查詢片段。
- Check(constraint[, name=None])
- 參數
constraint (str) – 條件約束 SQL。
name (str) – 條件約束名稱。
表示 CHECK 條件約束。
警告
MySQL 可能不支援在將條件約束與欄位定義內聯時使用
name
參數。解決方案是將具名的Check
條件約束放在模型的Meta.constraints
列表中,而不是欄位實例的constraints=[...]
列表中。
- class Function(name, arguments[, coerce=True[, python_value=None]])
- 參數
name (str) – 函式名稱。
arguments (tuple) – 函式的引數。
coerce (bool) – 從游標讀取函式傳回值時,是否強制將函式結果轉換為特定的資料類型。
python_value (callable) – 用於轉換游標傳回值的函式。
表示任意的 SQL 函式呼叫。
注意
建議使用
fn
輔助函式,而不是直接實例化此類別。使用
fn
呼叫任意 SQL 函式的範例# Query users and count of tweets authored. query = (User .select(User.username, fn.COUNT(Tweet.id).alias('ct')) .join(Tweet, JOIN.LEFT_OUTER, on=(User.id == Tweet.user_id)) .group_by(User.username) .order_by(fn.COUNT(Tweet.id).desc()))
- over([partition_by=None[, order_by=None[, start=None[, end=None[, window=None[, exclude=None]]]]]])
- 參數
注意
有關在 Peewee 中使用視窗函式的詳細指南,請參閱視窗函式章節。
範例
# Using a simple partition on a single column. query = (Sample .select( Sample.counter, Sample.value, fn.AVG(Sample.value).over([Sample.counter])) .order_by(Sample.counter)) # Equivalent example Using a Window() instance instead. window = Window(partition_by=[Sample.counter]) query = (Sample .select( Sample.counter, Sample.value, fn.AVG(Sample.value).over(window)) .window(window) # Note call to ".window()" .order_by(Sample.counter)) # Example using bounded window. query = (Sample .select(Sample.value, fn.SUM(Sample.value).over( partition_by=[Sample.counter], start=Window.CURRENT_ROW, # current row end=Window.following())) # unbounded following .order_by(Sample.id))
- filter(where)
- 參數
where – 用於篩選聚合的表達式。
將
FILTER (WHERE...)
子句新增到彙總函式。會評估 where 表達式以確定將哪些列饋送到彙總函式。Postgres 和 SQLite 支援此 SQL 功能。
- coerce([coerce=True])
- 參數
coerce (bool) – 是否嘗試將函式呼叫結果強制轉換為 Python 資料類型。
當 coerce 為
True
時,會使用多種啟發式方法推斷目標資料類型。請閱讀BaseModelCursorWrapper._initialize_columns
方法的原始碼以了解其運作方式。
- python_value([func=None])
- 參數
python_value (callable) – 用於轉換游標傳回值的函式。
指定在轉換資料庫游標傳回的值時要使用的特定函式。例如
# Get user and a list of their tweet IDs. The tweet IDs are # returned as a comma-separated string by the db, so we'll split # the result string and convert the values to python ints. convert_ids = lambda s: [int(i) for i in (s or '').split(',') if i] tweet_ids = (fn .GROUP_CONCAT(Tweet.id) .python_value(convert_ids)) query = (User .select(User.username, tweet_ids.alias('tweet_ids')) .group_by(User.username)) for user in query: print(user.username, user.tweet_ids) # e.g., # huey [1, 4, 5, 7] # mickey [2, 3, 6] # zaizee []
- fn()
fn()
輔助函式實際上是Function
的實例,它實作了__getattr__
掛鉤,以提供一個不錯的 API 來呼叫 SQL 函式。若要建立代表 SQL 函式呼叫的節點,請將函式名稱作為
fn
的屬性使用,然後像呼叫 Python 函式一樣提供引數# List users and the number of tweets they have authored, # from highest-to-lowest: sql_count = fn.COUNT(Tweet.id) query = (User .select(User, sql_count.alias('count')) .join(Tweet, JOIN.LEFT_OUTER) .group_by(User) .order_by(sql_count.desc())) # Get the timestamp of the most recent tweet: query = Tweet.select(fn.MAX(Tweet.timestamp)) max_timestamp = query.scalar() # Retrieve scalar result from query.
函式呼叫可以像其他任何項目一樣組合和巢狀
# Get users whose username begins with "A" or "a": a_users = User.select().where(fn.LOWER(fn.SUBSTR(User.username, 1, 1)) == 'a')
- class Window([partition_by=None[, order_by=None[, start=None[, end=None[, frame_type=None[, extends=None[, exclude=None[, alias=None]]]]]]]])
- 參數
partition_by (list) – 要分區的欄位清單。
order_by (list) – 要排序的欄位清單。
start – 一個
SQL
實例或一個表示視窗範圍開始位置的字串。end – 一個
SQL
實例或一個表示視窗範圍結束位置的字串。frame_type (str) –
Window.RANGE
、Window.ROWS
或Window.GROUPS
。extends – 要延伸的
Window
定義。或者,您可以指定視窗的別名。exclude – 框架排除,可以是
Window.CURRENT_ROW
、Window.GROUP
、Window.TIES
或Window.NO_OTHERS
其中之一。alias (str) – 視窗的別名。
表示 WINDOW 子句。
注意
有關在 Peewee 中使用視窗函式的詳細指南,請參閱視窗函式章節。
- RANGE
- ROWS
- GROUPS
指定視窗
frame_type
。請參閱框架類型:RANGE 與 ROWS 與 GROUPS。
- CURRENT_ROW
參考目前列,以用於開始/結束子句或框架排除參數。
- NO_OTHERS
- GROUP
- TIES
指定視窗框架排除參數。
- static preceding([value=None])
- 參數
value – 前面的列數。如果
None
為 UNBOUNDED。
產生適用於作為視窗範圍的
start
參數傳入的 SQL 的便利方法。
- static following([value=None])
- 參數
value – 後續的列數。如果
None
為 UNBOUNDED。
用於產生適用於傳入視窗範圍的
end
參數的 SQL 便利方法。
- as_rows()
- as_range()
- as_groups()
指定框架類型。
- exclude([frame_exclusion=None])
- 參數
frame_exclusion – 框架排除,為
Window.CURRENT_ROW
、Window.GROUP
、Window.TIES
或Window.NO_OTHERS
其中之一。
- alias([alias=None])
- 參數
alias (str) – 用於視窗的別名。
- Case(predicate, expression_tuples[, default=None]])
- 參數
predicate – CASE 查詢的述詞(可選)。
expression_tuples – 要評估的一個或多個案例。
default – 預設值(可選)。
- 傳回
CASE 語句的表示。
範例
Number = Table('numbers', ('val',)) num_as_str = Case(Number.val, ( (1, 'one'), (2, 'two'), (3, 'three')), 'a lot') query = Number.select(Number.val, num_as_str.alias('num_str')) # The above is equivalent to: # SELECT "val", # CASE "val" # WHEN 1 THEN 'one' # WHEN 2 THEN 'two' # WHEN 3 THEN 'three' # ELSE 'a lot' END AS "num_str" # FROM "numbers" num_as_str = Case(None, ( (Number.val == 1, 'one'), (Number.val == 2, 'two'), (Number.val == 3, 'three')), 'a lot') query = Number.select(Number.val, num_as_str.alias('num_str')) # The above is equivalent to: # SELECT "val", # CASE # WHEN "val" = 1 THEN 'one' # WHEN "val" = 2 THEN 'two' # WHEN "val" = 3 THEN 'three' # ELSE 'a lot' END AS "num_str" # FROM "numbers"
- class NodeList(nodes[, glue=' '[, parens=False]])
- 參數
nodes (list) – 零個或多個節點。
glue (str) – 將節點轉換為 SQL 時如何連接它們。
parens (bool) – 是否將產生的 SQL 包裹在括號中。
表示節點列表、多部分子句、參數列表等。
- class DQ(**query)
- 參數
query – 使用 Django 樣式查找的任意篩選表達式。
表示一個可組合的 Django 樣式篩選表達式,適用於
Model.filter()
或ModelSelect.filter()
方法。
- class OnConflict([action=None[, update=None[, preserve=None[, where=None[, conflict_target=None[, conflict_where=None[, conflict_constraint=None]]]]]]])
- 參數
action (str) – 解決衝突時要執行的動作。
update – 將欄位對應到新值的字典。
preserve – 應從原始 INSERT 保留其值的欄位列表。另請參閱
EXCLUDED
。where – 限制衝突解決的表達式。
conflict_target – 組成約束的欄位。
conflict_where – 如果約束目標是部分索引(帶有 WHERE 子句的索引),則需要比對約束目標的表達式。
conflict_constraint (str) – 用於衝突解決的約束名稱。目前僅 Postgres 支援。
表示資料修改查詢的衝突解決子句。
根據使用的資料庫驅動程式,可能需要上述一個或多個參數。
- preserve(*columns)
- 參數
columns – 應保留其值的欄位。
- update([_data=None[, **kwargs]])
- 參數
_data (dict) – 將欄位對應到新值的字典。
kwargs – 將欄位名稱對應到新值的字典。
update()
方法支援使用欄位到值的字典,或 表示相同的關鍵字引數來呼叫。
- where(*expressions)
- 參數
expressions – 限制衝突解決子句動作的表達式。
- conflict_target(*constraints)
- 參數
constraints – 用於衝突解決的目標欄位。
- conflict_where(*expressions)
- 參數
expressions – 比對衝突目標索引的表達式,以防衝突目標是部分索引。
- conflict_constraint(constraint)
- 參數
constraint (str) – 用於衝突解決的目標約束名稱。目前僅 Postgres 支援。
- class EXCLUDED
輔助物件,公開與
INSERT ... ON CONFLICT
一起使用的EXCLUDED
命名空間,以參照衝突資料中的值。這是一個「魔術」輔助物件,使用方式是透過存取對應特定欄位的屬性來使用。範例
class KV(Model): key = CharField(unique=True) value = IntegerField() # Create one row. KV.create(key='k1', value=1) # Demonstrate usage of EXCLUDED. # Here we will attempt to insert a new value for a given key. If that # key already exists, then we will update its value with the *sum* of its # original value and the value we attempted to insert -- provided that # the new value is larger than the original value. query = (KV.insert(key='k1', value=10) .on_conflict(conflict_target=[KV.key], update={KV.value: KV.value + EXCLUDED.value}, where=(EXCLUDED.value > KV.value))) # Executing the above query will result in the following data being # present in the "kv" table: # (key='k1', value=11) query.execute() # If we attempted to execute the query *again*, then nothing would be # updated, as the new value (10) is now less than the value in the # original row (11).
- class BaseQuery
所有其他查詢類別都繼承自的父類別。雖然您不會在程式碼中直接處理
BaseQuery
,但它實作了一些所有查詢類型通用的方法。- default_row_type = ROW.DICT
- dicts([as_dict=True])
- 參數
as_dict (bool) – 指定是否將資料列作為字典返回。
將資料列作為字典返回。
- tuples([as_tuples=True])
- 參數
as_tuple (bool) – 指定是否將資料列作為元組返回。
將資料列作為元組返回。
- namedtuples([as_namedtuple=True])
- 參數
as_namedtuple (bool) – 指定是否將資料列作為具名元組返回。
將資料列作為具名元組返回。
- objects([constructor=None])
- 參數
constructor – 接受資料列字典並返回任意物件的函數。
使用給定的建構函式,將資料列作為任意物件返回。
- sql()
- 傳回
包含查詢 SQL 和參數的 2 元組。
- execute(database)
- 參數
database (資料庫) – 要針對其執行查詢的資料庫。如果查詢先前已綁定到資料庫,則不是必要的。
執行查詢並返回結果 (取決於正在執行的查詢類型)。例如,選取查詢的返回結果將是對查詢結果的迭代器。
- iterator([database=None])
- 參數
database (資料庫) – 要針對其執行查詢的資料庫。如果查詢先前已綁定到資料庫,則不是必要的。
執行查詢並返回結果集的迭代器。對於大型結果集,此方法是較佳的選擇,因為在迭代期間不會將資料列快取在記憶體中。
注意
由於資料列未被快取,因此查詢可能僅迭代一次。後續迭代將返回空的結果集,因為游標已被消耗。
範例
query = StatTbl.select().order_by(StatTbl.timestamp).tuples() for row in query.iterator(db): process_row(row)
- __iter__()
執行查詢並返回結果集的迭代器。
與
iterator()
不同,此方法將導致資料列被快取,以允許有效率的迭代、索引和切片。
- __getitem__(value)
- 參數
value – 整數索引或切片。
從結果集中擷取資料列或資料列範圍。
- __len__()
返回結果集中的資料列數。
警告
這不會發出
COUNT()
查詢。相反地,會載入結果集,就像在正常迭代期間一樣,並從結果集的大小判斷長度。
- class RawQuery([sql=None[, params=None[, **kwargs]]])
- 參數
sql (str) – SQL 查詢。
params (tuple) – 參數 (可選)。
透過直接指定要執行的 SQL 來建立查詢。
- class Query([where=None[, order_by=None[, limit=None[, offset=None[, **kwargs]]]]])
- 參數
where – WHERE 子句的表示法。
order_by (tuple) – 要排序的欄或值。
limit (int) – LIMIT 子句的值。
offset (int) – OFFSET 子句的值。
支援方法鏈接 API 的查詢的基底類別。
- with_cte(*cte_list)
- 參數
cte_list – 零或多個
CTE
物件。
在查詢中包含指定的通用資料表運算式。任何先前指定的 CTE 都將被覆寫。如需通用資料表運算式的範例,請參閱 通用資料表運算式。
- cte(name[, recursive=False[, columns=None]])
- 參數
name (str) – 通用資料表運算式的別名。
recursive (bool) – 這會是遞迴 CTE 嗎?
columns (list) – 欄名稱清單 (字串)。
表示查詢將用作通用資料表運算式。例如,如果我們正在建模類別樹,並使用父連結外鍵,我們可以透過遞迴 CTE 擷取所有類別及其絕對深度
class Category(Model): name = TextField() parent = ForeignKeyField('self', backref='children', null=True) # The base case of our recursive CTE will be categories that are at # the root level -- in other words, categories without parents. roots = (Category .select(Category.name, Value(0).alias('level')) .where(Category.parent.is_null()) .cte(name='roots', recursive=True)) # The recursive term will select the category name and increment # the depth, joining on the base term so that the recursive term # consists of all children of the base category. RTerm = Category.alias() recursive = (RTerm .select(RTerm.name, (roots.c.level + 1).alias('level')) .join(roots, on=(RTerm.parent == roots.c.id))) # Express <base term> UNION ALL <recursive term>. cte = roots.union_all(recursive) # Select name and level from the recursive CTE. query = (cte .select_from(cte.c.name, cte.c.level) .order_by(cte.c.name)) for category in query: print(category.name, category.level)
如需更多 CTE 範例,請參閱 通用資料表運算式。
- where(*expressions)
- 參數
expressions – 零或多個要包含在 WHERE 子句中的運算式。
在查詢的 WHERE 子句中包含指定的運算式。這些運算式將與任何先前指定的 WHERE 運算式進行 AND 運算。
範例選取使用者,其中使用者名稱等於 'somebody'
sq = User.select().where(User.username == 'somebody')
範例選取由身為編輯者或管理員的使用者所發佈的推文
sq = Tweet.select().join(User).where( (User.is_editor == True) | (User.is_admin == True))
範例刪除不再處於活動狀態的使用者所發佈的推文
inactive_users = User.select().where(User.active == False) dq = (Tweet .delete() .where(Tweet.user.in_(inactive_users))) dq.execute() # Return number of tweets deleted.
注意
where()
呼叫可鏈接。多個呼叫將以 “AND” 進行串連。
- orwhere(*expressions)
- 參數
expressions – 零或多個要包含在 WHERE 子句中的運算式。
在查詢的 WHERE 子句中包含指定的運算式。此方法與
Query.where()
方法相同,不同之處在於這些運算式將與任何先前指定的 WHERE 運算式進行 OR 運算。
- order_by(*values)
- 參數
values – 零或多個要排序的類似欄的物件。
定義 ORDER BY 子句。任何先前指定的值都將被覆寫。
- order_by_extend(*values)
- 參數
values – 零或多個要排序的類似欄的物件。
使用指定的值擴充任何先前指定的 ORDER BY 子句。
- limit([value=None])
- 參數
value (int) – 指定 LIMIT 子句的值。
- offset([value=None])
- 參數
value (int) – 指定 OFFSET 子句的值。
- paginate(page[, paginate_by=20])
- 參數
page (int) – 結果的頁碼 (從 1 開始)。
paginate_by (int) – 每頁的資料列數。
以更直覺的方式指定 LIMIT 和 OFFSET 的便捷方法。
此功能旨在考慮網站分頁,因此第一頁從
page=1
開始。
- class SelectQuery
選取查詢輔助類別,實作運算子重載以建立複合查詢。
- select_from(*columns)
- 參數
columns – 從內部查詢中選擇的一個或多個欄位。
- 傳回
一個新的查詢,會包裝呼叫此方法的查詢。
建立一個新的查詢,包裝目前的(呼叫此方法的)查詢。例如,假設您有一個簡單的
UNION
查詢,並且需要在 union 結果集上應用聚合。要做到這一點,您需要寫類似這樣的東西:SELECT "u"."owner", COUNT("u"."id") AS "ct" FROM ( SELECT "id", "owner", ... FROM "cars" UNION SELECT "id", "owner", ... FROM "motorcycles" UNION SELECT "id", "owner", ... FROM "boats") AS "u" GROUP BY "u"."owner"
select_from()
方法旨在簡化此類查詢的建構。Peewee 程式碼範例
class Car(Model): owner = ForeignKeyField(Owner, backref='cars') # ... car-specific fields, etc ... class Motorcycle(Model): owner = ForeignKeyField(Owner, backref='motorcycles') # ... motorcycle-specific fields, etc ... class Boat(Model): owner = ForeignKeyField(Owner, backref='boats') # ... boat-specific fields, etc ... cars = Car.select(Car.owner) motorcycles = Motorcycle.select(Motorcycle.owner) boats = Boat.select(Boat.owner) union = cars | motorcycles | boats query = (union .select_from(union.c.owner, fn.COUNT(union.c.id)) .group_by(union.c.owner))
- union_all(dest)
使用
dest
建立 UNION ALL 查詢。
- __add__(dest)
使用
dest
建立 UNION ALL 查詢。
- union(dest)
使用
dest
建立 UNION 查詢。
- __or__(dest)
使用
dest
建立 UNION 查詢。
- intersect(dest)
使用
dest
建立 INTERSECT 查詢。
- __and__(dest)
使用
dest
建立 INTERSECT 查詢。
- except_(dest)
使用
dest
建立 EXCEPT 查詢。請注意,方法名稱後有一個「_」字元,因為except
是 Python 的保留字。
- __sub__(dest)
使用
dest
建立 EXCEPT 查詢。
- class SelectBase
Select
和CompoundSelect
查詢的基底類別。- peek(database[, n=1])
- 參數
database (Database) – 要執行查詢的資料庫。
n (int) – 要回傳的列數。
- 傳回
如果 n = 1,則為單列,否則為列的清單。
執行查詢並從游標開頭回傳給定數量的列。可以安全地多次呼叫此函數,並且始終會回傳前 N 列的結果。
- first(database[, n=1])
- 參數
database (Database) – 要執行查詢的資料庫。
n (int) – 要回傳的列數。
- 傳回
如果 n = 1,則為單列,否則為列的清單。
與
peek()
方法類似,差別在於會將LIMIT
應用於查詢,以確保僅回傳n
列。對相同的n
值多次呼叫不會導致多次執行。查詢會就地更改,因此無法呼叫
first()
,然後使用相同的查詢物件迭代完整結果集。再次強調,這樣做是為了確保多次呼叫first()
不會導致多次查詢執行。
- scalar(database[, as_tuple=False[, as_dict=False]])
- 參數
database (Database) – 要執行查詢的資料庫。
as_tuple (bool) – 是否將結果以 tuple 形式回傳?
as_dict (bool) – 是否將結果以 dict 形式回傳?
- 傳回
單一純量值。如果
as_tuple = True
,則回傳列 tuple。如果as_dict = True
,則回傳列 dict。
從結果的第一列回傳純量值。如果預期有多個純量值(例如,單一查詢中的多個聚合),您可以指定
as_tuple=True
以取得列 tuple。範例
query = Note.select(fn.MAX(Note.timestamp)) max_ts = query.scalar(db) query = Note.select(fn.MAX(Note.timestamp), fn.COUNT(Note.id)) max_ts, n_notes = query.scalar(db, as_tuple=True) query = Note.select(fn.COUNT(Note.id).alias('count')) assert query.scalar(db, as_dict=True) == {'count': 123}
- class CompoundSelectQuery(lhs, op, rhs)
- 參數
lhs (SelectBase) – Select 或 CompoundSelect 查詢。
op (str) – 運算子 (例如 UNION、INTERSECT、EXCEPT)。
rhs (SelectBase) – Select 或 CompoundSelect 查詢。
表示複合 SELECT 查詢的類別。
- class Select([from_list=None[, columns=None[, group_by=None[, having=None[, distinct=None[, windows=None[, for_update=None[, for_update_of=None[, for_update_nowait=None[, **kwargs]]]]]]]]]])
- 參數
from_list (list) – FROM 子句的來源清單。
columns (list) – 要選擇的欄位或值。
group_by (list) – 要分組的欄位或值清單。
having (Expression) – HAVING 子句的表示式。
distinct – 布林值或類似欄位的物件清單。
windows (list) –
Window
子句清單。for_update – 布林值或字串,指出是否使用 SELECT…FOR UPDATE。
for_update_of – FOR UPDATE OF 子句的一個或多個表格。
for_update_nowait (bool) – 指定 NOWAIT 鎖定。
表示 SELECT 查詢的類別。
注意
您通常不會直接實例化此類別,最常見的是使用像是
Table.select()
或Model.select()
的工廠方法。可以將 select 查詢的方法串連在一起。
從資料庫中選擇一些使用者實例的範例。僅選擇
id
和username
欄位。迭代時,會回傳User
模型的實例query = User.select(User.id, User.username) for user in query: print(user.username)
選擇使用者以及使用者發出的推文數量的範例。回傳的
User
實例將有一個額外屬性 ‘count’,對應於發出的推文數量query = (User .select(User, fn.COUNT(Tweet.id).alias('count')) .join(Tweet, JOIN.LEFT_OUTER) .group_by(User)) for user in query: print(user.username, 'has tweeted', user.count, 'times')
注意
雖然可以直接實例化
Select
,但更常見的是使用方法鏈式 API 來建構查詢。- columns(*columns)
- 參數
columns – 要 SELECT 的零個或多個類似欄位的物件。
指定要 SELECT 的欄位或類似欄位的值。
- select(*columns)
- 參數
columns – 要 SELECT 的零個或多個類似欄位的物件。
與
Select.columns()
相同,為了向後相容性而提供。
- select_extend(*columns)
- 參數
columns – 要 SELECT 的零個或多個類似欄位的物件。
使用給定的欄位擴展目前的選擇。
範例
def get_users(with_count=False): query = User.select() if with_count: query = (query .select_extend(fn.COUNT(Tweet.id).alias('count')) .join(Tweet, JOIN.LEFT_OUTER) .group_by(User)) return query
- from_(*sources)
- 參數
sources – FROM 子句的零個或多個來源。
指定應在 FROM 子句中使用哪些類似表格的物件。
User = Table('users') Tweet = Table('tweets') query = (User .select(User.c.username, Tweet.c.content) .from_(User, Tweet) .where(User.c.id == Tweet.c.user_id)) for row in query.execute(db): print(row['username'], '->', row['content'])
- join(dest[, join_type='INNER'[, on=None]])
- 參數
dest – 表格或類似表格的物件。
join_type (str) – JOIN 的類型,預設為 “INNER”。
on (Expression) – Join 的謂詞。
聯結類型可以是下列其中之一
JOIN.INNER
JOIN.LEFT_OUTER
JOIN.RIGHT_OUTER
JOIN.FULL
JOIN.FULL_OUTER
JOIN.CROSS
表達一個 JOIN。
User = Table('users', ('id', 'username')) Note = Table('notes', ('id', 'user_id', 'content')) query = (Note .select(Note.content, User.username) .join(User, on=(Note.user_id == User.id)))
- group_by(*columns)
- 參數
values – 要分組的零個或多個類似欄位的物件。
定義 GROUP BY 子句。任何先前指定的值都將被覆寫。
此外,若要指定給定表格的所有欄位,您可以傳遞表格/模型物件來代替個別欄位。
範例
query = (User .select(User, fn.Count(Tweet.id).alias('count')) .join(Tweet) .group_by(User))
- group_by_extend(*columns)
- 參數
values – 要分組的零個或多個類似欄位的物件。
使用給定的欄位擴展 GROUP BY 子句。
- having(*expressions)
- 參數
expressions – 要包含在 HAVING 子句中的零個或多個表達式。
在查詢的 HAVING 子句中包含給定的表達式。這些表達式將與任何先前指定的 HAVING 表達式進行 AND 運算。
- distinct(*columns)
- 參數
columns – 零個或多個類似欄位的物件。
指示此查詢是否應使用 DISTINCT 子句。透過指定單一值
True
,查詢將使用簡單的 SELECT DISTINCT。指定一個或多個欄位將產生 SELECT DISTINCT ON。
- window(*windows)
- 參數
windows – 零個或多個
Window
物件。
定義 WINDOW 子句。任何先前指定的值都將被覆寫。
範例
# Equivalent example Using a Window() instance instead. window = Window(partition_by=[Sample.counter]) query = (Sample .select( Sample.counter, Sample.value, fn.AVG(Sample.value).over(window)) .window(window) # Note call to ".window()" .order_by(Sample.counter))
- for_update([for_update=True[, of=None[, nowait=None]]])
- 參數
for_update – 布林值或指示所需表達式的字串,例如 “FOR SHARE”。
of – 一個或多個要限制鎖定的模型。
nowait (bool) – 指定鎖定時的 NOWAIT 選項。
- class _WriteQuery(table[, returning=None[, **kwargs]])
- 參數
table (Table) – 要寫入的表格。
returning (list) – RETURNING 子句的欄位清單。
寫入查詢的基底類別。
- returning(*returning)
- 參數
returning – RETURNING 子句的零個或多個類似欄位的物件。
指定查詢的 RETURNING 子句(如果您的資料庫支援)。
query = (User .insert_many([{'username': 'foo'}, {'username': 'bar'}, {'username': 'baz'}]) .returning(User.id, User.username) .namedtuples()) data = query.execute() for row in data: print('added:', row.username, 'with id=', row.id)
- class Update(table[, update=None[, **kwargs]])
- 參數
table (Table) – 要更新的表格。
update (dict) – 要更新的資料。
代表 UPDATE 查詢的類別。
範例
PageView = Table('page_views') query = (PageView .update({PageView.c.page_views: PageView.c.page_views + 1}) .where(PageView.c.url == url)) query.execute(database)
- from_(*sources)
- 參數
sources (Source) – 一個或多個
Table
、Model
、查詢或ValuesList
以進行聯結。
使用 Postgres 支援的 UPDATE ... FROM 語法指定要聯結的其他表格。Postgres 文件提供了更多詳細資訊,但總結來說
當存在
FROM
子句時,實際發生的情況是將目標表格聯結到 from_list 中提到的表格,並且聯結的每個輸出列都代表目標表格的更新操作。使用FROM
時,您應該確保聯結為每個要修改的列產生最多一個輸出列。範例
# Update multiple users in a single query. data = [('huey', True), ('mickey', False), ('zaizee', True)] vl = ValuesList(data, columns=('username', 'is_admin'), alias='vl') # Here we'll update the "is_admin" status of the above users, # "joining" the VALUES() on the "username" column. query = (User .update(is_admin=vl.c.is_admin) .from_(vl) .where(User.username == vl.c.username))
上面的查詢會產生以下 SQL
UPDATE "users" SET "is_admin" = "vl"."is_admin" FROM ( VALUES ('huey', t), ('mickey', f), ('zaizee', t)) AS "vl"("username", "is_admin") WHERE ("users"."username" = "vl"."username")
- class Insert(table[, insert=None[, columns=None[, on_conflict=None[, **kwargs]]]])
- 參數
table (Table) – 要將資料 INSERT 到的表格。
insert – dict、清單或查詢。
columns (list) – 當
insert
是清單或查詢時的欄位清單。on_conflict – 衝突解決策略。
代表 INSERT 查詢的類別。
- as_rowcount([as_rowcount=True])
- 參數
as_rowcount (bool) – 是否返回修改的列數(而不是最後插入的列 ID)。
預設情況下,在不自動使用 RETURNING 的資料庫(目前為 Sqlite 和 MySQL)上,Peewee 3.12 到 3.14.10 版本在執行批次插入時會返回修改的列數。此變更已還原,因此批次插入預設會返回
cursor.lastrowid
的值。如果您希望收到插入的列數,請指定
as_rowcount()
。db = MySQLDatabase(...) query = User.insert_many([...]) # By default, the last rowid is returned: #last_id = query.execute() # To get the modified row-count: rowcount = query.as_rowcount().execute()
- on_conflict_ignore([ignore=True])
- 參數
ignore (bool) – 是否加入 ON CONFLICT IGNORE 子句。
指定 IGNORE 衝突解決策略。
- on_conflict_replace([replace=True])
- 參數
replace (bool) – 是否加入 ON CONFLICT REPLACE 子句。
指定 REPLACE 衝突解決策略。
- on_conflict([action=None[, update=None[, preserve=None[, where=None[, conflict_target=None[, conflict_where=None[, conflict_constraint=None]]]]]]])
- 參數
action (str) – 解決衝突時採取的動作。如果為空白,則假設動作為「update」。
update – 將欄位對應到新值的字典。
preserve – 一個欄位列表,其值應從原始的 INSERT 保留。
where – 限制衝突解決的表達式。
conflict_target – 組成約束的欄位。
conflict_where – 如果約束目標是部分索引(帶有 WHERE 子句的索引),則需要比對約束目標的表達式。
conflict_constraint (str) – 用於衝突解決的約束名稱。目前僅 Postgres 支援。
指定用於衝突解決的
OnConflict
子句的參數。範例
class User(Model): username = TextField(unique=True) last_login = DateTimeField(null=True) login_count = IntegerField() def log_user_in(username): now = datetime.datetime.now() # INSERT a new row for the user with the current timestamp and # login count set to 1. If the user already exists, then we # will preserve the last_login value from the "insert()" clause # and atomically increment the login-count. userid = (User .insert(username=username, last_login=now, login_count=1) .on_conflict( conflict_target=[User.username], preserve=[User.last_login], update={User.login_count: User.login_count + 1}) .execute()) return userid
使用特殊
EXCLUDED
命名空間的範例class KV(Model): key = CharField(unique=True) value = IntegerField() # Create one row. KV.create(key='k1', value=1) # Demonstrate usage of EXCLUDED. # Here we will attempt to insert a new value for a given key. If that # key already exists, then we will update its value with the *sum* of its # original value and the value we attempted to insert -- provided that # the new value is larger than the original value. query = (KV.insert(key='k1', value=10) .on_conflict(conflict_target=[KV.key], update={KV.value: KV.value + EXCLUDED.value}, where=(EXCLUDED.value > KV.value))) # Executing the above query will result in the following data being # present in the "kv" table: # (key='k1', value=11) query.execute() # If we attempted to execute the query *again*, then nothing would be # updated, as the new value (10) is now less than the value in the # original row (11).
- class Delete
表示 DELETE 查詢的類別。
- class Index(name, table, expressions[, unique=False[, safe=False[, where=None[, using=None]]]])
- 參數
name (str) – 索引名稱。
table (Table) – 要在其上建立索引的表格。
expressions – 要建立索引的欄位列表 (或運算式)。
unique (bool) – 索引是否為 UNIQUE。
safe (bool) – 是否加入 IF NOT EXISTS 子句。
where (Expression) – 索引的可選 WHERE 子句。
using (str) – 索引演算法。
- safe([_safe=True])
- 參數
_safe (bool) – 是否加入 IF NOT EXISTS 子句。
- where(*expressions)
- 參數
expressions – 零或多個要包含在 WHERE 子句中的運算式。
在索引的 WHERE 子句中包含給定的運算式。運算式將與先前指定的任何 WHERE 運算式進行 AND 運算。
- using([_using=None])
- 參數
_using (str) – 為 USING 子句指定索引演算法。
- class ModelIndex(model, fields[, unique=False[, safe=True[, where=None[, using=None[, name=None]]]]])
- 參數
model (Model) – 要在其上建立索引的 Model 類別。
fields (list) – 要建立索引的欄位。
unique (bool) – 索引是否為 UNIQUE。
safe (bool) – 是否加入 IF NOT EXISTS 子句。
where (Expression) – 索引的可選 WHERE 子句。
using (str) – 索引演算法或類型,例如 'BRIN'、'GiST' 或 'GIN'。
name (str) – 可選的索引名稱。
用於宣告模型索引的表達式方法。
範例
class Article(Model): name = TextField() timestamp = TimestampField() status = IntegerField() flags = BitField() is_sticky = flags.flag(1) is_favorite = flags.flag(2) # CREATE INDEX ... ON "article" ("name", "timestamp") idx = ModelIndex(Article, (Article.name, Article.timestamp)) # CREATE INDEX ... ON "article" ("name", "timestamp") WHERE "status" = 1 idx = idx.where(Article.status == 1) # CREATE UNIQUE INDEX ... ON "article" ("timestamp" DESC, "flags" & 2) WHERE "status" = 1 idx = ModelIndex( Article, (Article.timestamp.desc(), Article.flags.bin_and(2)), unique = True).where(Article.status == 1)
您也可以使用
Model.index()
idx = Article.index(Article.name, Article.timestamp).where(Article.status == 1)
若要將索引新增至模型定義,請使用
Model.add_index()
idx = Article.index(Article.name, Article.timestamp).where(Article.status == 1) # Add above index definition to the model definition. When you call # Article.create_table() (or database.create_tables([Article])), the # index will be created. Article.add_index(idx)
欄位
- class Field([null=False[, index=False[, unique=False[, column_name=None[, default=None[, primary_key=False[, constraints=None[, sequence=None[, collation=None[, unindexed=False[, choices=None[, help_text=None[, verbose_name=None[, index_type=None]]]]]]]]]]]]]])
- 參數
null (bool) – 欄位允許 NULL 值。
index (bool) – 在欄位上建立索引。
unique (bool) – 在欄位上建立唯一索引。
column_name (str) – 為欄位指定欄位名稱。
default – 預設值(在 Python 中強制執行,而不是在伺服器上)。
primary_key (bool) – 欄位是主鍵。
constraints (list) – 要套用到欄位的限制列表,例如:
[Check('price > 0')]
。sequence (str) – 欄位的序號名稱。
collation (str) – 欄位的定序名稱。
unindexed (bool) – 宣告欄位為 UNINDEXED(僅限 sqlite)。
choices (list) – 一個由 2 元組組成的可迭代物件,將欄位值對應到顯示標籤。僅用於中繼資料目的,例如,有助於顯示欄位值選項下拉式清單。
help_text (str) – 欄位的說明文字,僅用於中繼資料目的。
verbose_name (str) – 欄位的詳細名稱,僅用於中繼資料目的。
index_type (str) – 指定索引類型(僅限 postgres),例如 'BRIN'。
Model
上的欄位類似於表格上的欄位。- field_type = '<一些 欄位 類型>'
用於將此欄位對應到欄位類型的屬性,例如 “INT”。請參閱來源中的
FIELD
物件以取得更多資訊。
- model
欄位綁定的模型。
- name
欄位的名稱。
- db_value(value)
將 Python 值強制轉換為適合儲存在資料庫中的值。在特殊資料類型上操作的子類別很可能想要覆寫此方法。
- python_value(value)
將來自資料庫的值強制轉換為 Python 物件。在特殊資料類型上操作的子類別很可能想要覆寫此方法。
- coerce(value)
此方法是一種簡寫,預設情況下,
db_value()
和python_value()
都會使用此方法。- 參數
value – 來自應用程式或後端的任意資料
- 回傳類型
python 資料類型
- class IntegerField
用於儲存整數的欄位類別。
- class BigIntegerField
用於儲存大整數的欄位類別(如果資料庫支援)。
- class SmallIntegerField
用於儲存小整數的欄位類別(如果資料庫支援)。
- class AutoField
用於儲存自動遞增主鍵的欄位類別。
注意
在 SQLite 中,基於效能考量,預設的主鍵類型僅使用現有最大值 + 1 作為新值,而非曾經出現的最大值 + 1。這表示已刪除的記錄可以重複使用它們的主鍵。再加上 SQLite 預設禁用外鍵(表示即使您明確指定,也會忽略 ON DELETE),這可能會導致令人驚訝且危險的行為。為了避免這種情況,您可能需要在使用
SqliteDatabase
實例化時,使用AutoIncrementField
和pragmas=[('foreign_keys', 'on')]
的其中一個或兩個。
- class BigAutoField
用於儲存使用 64 位元的自動遞增主鍵的欄位類別。
- class IdentityField([generate_always=False])
- 參數
generate_always (bool) – 如果指定,則始終會產生身分識別(在 INSERT 期間明確指定值會引發程式錯誤)。否則,身分識別值只會在需要時產生。
用於儲存使用新的 Postgres 10 IDENTITY 欄位類型自動遞增主鍵的欄位類別。欄位定義最終會像這樣:
id = IdentityField() # "id" INT GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY
注意
僅限 Postgres 10.0 及更新版本支援。
- class FloatField
用於儲存浮點數的欄位類別。
- class DoubleField
用於儲存雙精度浮點數的欄位類別。
- class DecimalField([max_digits=10[, decimal_places=5[, auto_round=False[, rounding=None[, **kwargs]]]]])
- 參數
max_digits (int) – 要儲存的最大位數。
decimal_places (int) – 最大精度。
auto_round (bool) – 自動四捨五入值。
rounding –
預設為
decimal.DefaultContext.rounding
。用於儲存十進位數的欄位類別。值表示為
decimal.Decimal
物件。
- class CharField([max_length=255])
用於儲存字串的欄位類別。
注意
超出長度的值不會自動截斷。
- class FixedCharField
用於儲存固定長度字串的欄位類別。
注意
超出長度的值不會自動截斷。
- class TextField
用於儲存文字的欄位類別。
- class BlobField
用於儲存二進位資料的欄位類別。
- class BitField
用於在 64 位元整數欄位中儲存選項的欄位類別。
用法
class Post(Model): content = TextField() flags = BitField() is_favorite = flags.flag(1) is_sticky = flags.flag(2) is_minimized = flags.flag(4) is_deleted = flags.flag(8) >>> p = Post() >>> p.is_sticky = True >>> p.is_minimized = True >>> print(p.flags) # Prints 4 | 2 --> "6" 6 >>> p.is_favorite False >>> p.is_sticky True
我們也可以使用 Post 類別上的標誌在查詢中建立運算式
# Generates a WHERE clause that looks like: # WHERE (post.flags & 1 != 0) query = Post.select().where(Post.is_favorite) # Query for sticky + favorite posts: query = Post.select().where(Post.is_sticky & Post.is_favorite)
當在
BitField
中大量更新一個或多個位元時,您可以使用位元運算子來設定或清除一個或多個位元# Set the 4th bit on all Post objects. Post.update(flags=Post.flags | 8).execute() # Clear the 1st and 3rd bits on all Post objects. Post.update(flags=Post.flags & ~(1 | 4)).execute()
對於簡單的操作,標誌提供了方便的
set()
和clear()
方法,用於設定或清除個別位元# Set the "is_deleted" bit on all posts. Post.update(flags=Post.is_deleted.set()).execute() # Clear the "is_deleted" bit on all posts. Post.update(flags=Post.is_deleted.clear()).execute()
- flag([value=None])
- 參數
value (int) – 與標誌相關聯的值,通常是 2 的冪次。
傳回一個描述符,可以取得或設定整體值中的特定位元。當在類別本身上存取時,它會傳回一個適合在查詢中使用的
Expression
物件。如果未提供值,則假定每個標誌將是 2 的遞增冪次,因此如果您有四個標誌,它們的值將為 1、2、4、8。
- class BigBitField
用於在
BLOB
中儲存任意大小位元圖的欄位類別。欄位會根據需要擴展底層緩衝區,確保有足夠的資料位元組來支援儲存的資料位元數。使用範例
class Bitmap(Model): data = BigBitField() bitmap = Bitmap() # Sets the ith bit, e.g. the 1st bit, the 11th bit, the 63rd, etc. bits_to_set = (1, 11, 63, 31, 55, 48, 100, 99) for bit_idx in bits_to_set: bitmap.data.set_bit(bit_idx) # We can test whether a bit is set using "is_set": assert bitmap.data.is_set(11) assert not bitmap.data.is_set(12) # We can clear a bit: bitmap.data.clear_bit(11) assert not bitmap.data.is_set(11) # We can also "toggle" a bit. Recall that the 63rd bit was set earlier. assert bitmap.data.toggle_bit(63) is False assert bitmap.data.toggle_bit(63) is True assert bitmap.data.is_set(63) # BigBitField supports item accessor by bit-number, e.g.: assert bitmap.data[63] bitmap.data[0] = 1 del bitmap.data[0] # We can also combine bitmaps using bitwise operators, e.g. b = Bitmap(data=b'\x01') b.data |= b'\x02' assert list(b.data) == [1, 1, 0, 0, 0, 0, 0, 0] assert len(b.data) == 1
- clear()
清除位元圖並將長度設定為 0。
- set_bit(idx)
- 參數
idx (int) – 要設定的位元,從零開始索引。
設定位元圖中的第 idx 個位元。
- clear_bit(idx)
- 參數
idx (int) – 要清除的位元,從零開始索引。
清除位元圖中的第 idx 個位元。
- toggle_bit(idx)
- 參數
idx (int) – 要切換的位元,從零開始索引。
- 傳回
無論位元是否設定。
切換位元圖中的第 idx 個位元,並傳回位元是否已設定。
範例
>>> bitmap = Bitmap() >>> bitmap.data.toggle_bit(10) # Toggle the 10th bit. True >>> bitmap.data.toggle_bit(10) # This will clear the 10th bit. False
- is_set(idx)
- 參數
idx (int) – 位元索引,從零開始索引。
- 傳回
無論位元是否設定。
傳回布林值,表示第 idx 個位元是否已設定。
- __setitem__(idx, value)
將
idx
的位元設定為值(True 或 False)。
- __delitem__(idx)
與
clear_bit()
相同
- __len__()
傳回位元圖的長度,以位元組為單位。
- __iter__()
傳回一個迭代器,為位元圖中的每個位元產生 1 或 0。
- __and__(other)
- 參數
other –
BigBitField
、bytes
、bytearray
或memoryview
物件其中之一。- 傳回
兩個位元圖的位元
and
。
- __or__(other)
- 參數
other –
BigBitField
、bytes
、bytearray
或memoryview
物件其中之一。- 傳回
兩個位元圖的位元
or
。
- __xor__(other)
- 參數
other –
BigBitField
、bytes
、bytearray
或memoryview
物件其中之一。- 傳回
兩個位元圖的位元
xor
運算。
- class UUIDField
用於儲存
uuid.UUID
物件的欄位類別。使用 Postgres 時,底層資料行的資料類型將為 UUID。由於 SQLite 和 MySQL 沒有原生的 UUID 類型,因此 UUID 會改為儲存為 VARCHAR。
- class BinaryUUIDField
用於以 16 位元組有效儲存
uuid.UUID
物件的欄位類別。使用資料庫的 BLOB 資料類型(或 MySQL 中的 VARBINARY,或 Postgres 中的 BYTEA)。
- class DateTimeField([formats=None[, **kwargs]])
- 參數
formats (list) – 將字串強制轉換為日期時間時要使用的格式字串清單。
用於儲存
datetime.datetime
物件的欄位類別。接受一個特殊參數
formats
,其中包含可以用來編碼日期時間的格式清單(對於不支援原生日期時間資料類型的資料庫)。預設支援的格式為'%Y-%m-%d %H:%M:%S.%f' # year-month-day hour-minute-second.microsecond '%Y-%m-%d %H:%M:%S' # year-month-day hour-minute-second '%Y-%m-%d' # year-month-day
注意
SQLite 沒有原生的日期時間資料類型,因此日期時間會以字串形式儲存。Peewee 會透明地處理此問題,但如果您有現有的資料,則應確保其儲存為
YYYY-mm-dd HH:MM:SS
或其他支援的格式之一。- year
在查詢中參考欄位中儲存的值的年份。
Blog.select().where(Blog.pub_date.year == 2018)
- month
在查詢中參考欄位中儲存的值的月份。
- day
在查詢中參考欄位中儲存的值的日期。
- hour
在查詢中參考欄位中儲存的值的小時。
- minute
在查詢中參考欄位中儲存的值的分鐘。
- second
在查詢中參考欄位中儲存的值的秒數。
- to_timestamp()
此方法會傳回資料庫特定的函數呼叫,讓您能夠將給定的日期時間值當作數字時間戳記來使用。這有時可以簡化以相容方式執行日期數學運算等工作。
範例
# Find all events that are exactly 1 hour long. query = (Event .select() .where((Event.start.to_timestamp() + 3600) == Event.stop.to_timestamp()) .order_by(Event.start))
- truncate(date_part)
- 參數
date_part (str) – year、month、day、hour、minute 或 second。
- 傳回
將日期/時間截斷為指定解析度的運算式節點。
將欄位中的值截斷為給定的部分。例如,此方法對於尋找指定月份內的所有列很有用。
- class DateField([formats=None[, **kwargs]])
- 參數
formats (list) – 將字串強制轉換為日期時要使用的格式字串清單。
用於儲存
datetime.date
物件的欄位類別。接受一個特殊參數
formats
,其中包含可以用來編碼日期時間的格式清單(對於不支援原生日期資料類型的資料庫)。預設支援的格式為'%Y-%m-%d' # year-month-day '%Y-%m-%d %H:%M:%S' # year-month-day hour-minute-second '%Y-%m-%d %H:%M:%S.%f' # year-month-day hour-minute-second.microsecond
注意
如果傳入的值不符合任何格式,則會依原樣傳回。
- year
在查詢中參考欄位中儲存的值的年份。
Person.select().where(Person.dob.year == 1983)
- month
在查詢中參考欄位中儲存的值的月份。
- day
在查詢中參考欄位中儲存的值的日期。
- to_timestamp()
- truncate(date_part)
請參閱
DateTimeField.truncate()
。請注意,對於DateField
而言,只有 year、month 和 day 才有意義。
- class TimeField([formats=None[, **kwargs]])
- 參數
formats (list) – 將字串強制轉換為時間時要使用的格式字串清單。
用於儲存
datetime.time
物件(而非timedelta
)的欄位類別。接受一個特殊參數
formats
,其中包含可以用來編碼日期時間的格式清單(對於不支援原生時間資料類型的資料庫)。預設支援的格式為'%H:%M:%S.%f' # hour:minute:second.microsecond '%H:%M:%S' # hour:minute:second '%H:%M' # hour:minute '%Y-%m-%d %H:%M:%S.%f' # year-month-day hour-minute-second.microsecond '%Y-%m-%d %H:%M:%S' # year-month-day hour-minute-second
注意
如果傳入的值不符合任何格式,則會依原樣傳回。
- hour
在查詢中參考欄位中儲存的值的小時。
evening_events = Event.select().where(Event.time.hour > 17)
- minute
在查詢中參考欄位中儲存的值的分鐘。
- second
在查詢中參考欄位中儲存的值的秒數。
- class TimestampField([resolution=1[, utc=False[, **kwargs]]])
- 參數
resolution – 可以提供為 10 的冪,或提供為指數,表示要儲存的小數位數。
utc (bool) – 將時間戳記視為 UTC。
用於將日期時間儲存為整數時間戳記的欄位類別。支援次秒解析度,方法是乘以 10 的冪以取得整數。
如果
resolution
參數為0
或1
,則時間戳記會使用秒解析度儲存。介於2
和6
之間的解析度會被視為小數位數,例如,resolution=3
對應到毫秒。或者,小數可以提供為 10 的倍數,例如,resolution=10
將會儲存 1/10 秒的解析度。resolution
參數可以是 0-6 或 10、100 等,最高可達 1000000(對於微秒解析度)。這允許次秒精確度,同時仍然使用IntegerField
進行儲存。預設值為秒解析度。也接受布林參數
utc
,用來指示時間戳記是否應為 UTC。預設值為False
。最後,欄位
default
是目前的時間戳記。如果您不想要此行為,則明確傳入default=None
。
- class IPField
用於有效儲存 IPv4 位址(以整數形式)的欄位類別。
- class BooleanField
用於儲存布林值的欄位類別。
- class BareField([coerce=None[, **kwargs]])
- 參數
coerce – 用於將原始值轉換為特定格式的可選函數。
未指定資料類型的欄位類別(僅限 SQLite)。
由於資料類型不會強制執行,因此您可以宣告沒有任何資料類型的欄位。SQLite 虛擬表格也常使用中繼欄或未類型化的欄,因此在這些情況下,您可能也會想要使用未類型化的欄位。
接受一個特殊的
coerce
參數,此參數是一個函數,它接收來自資料庫的值,並將其轉換為適當的 Python 型別。
- class ForeignKeyField(model[, field=None[, backref=None[, on_delete=None[, on_update=None[, deferrable=None[, object_id_name=None[, lazy_load=True[, constraint_name=None[, **kwargs]]]]]]]]])
- 參數
model (Model) – 要參考的 Model,或是在宣告自參考外鍵時使用的字串 'self'。
field (Field) – 要在
model
上參考的欄位(預設為主鍵)。backref (str) – 反向參照的存取器名稱,或使用 “+” 停用反向參照存取器。
on_delete (str) – ON DELETE 動作,例如
'CASCADE'
。on_update (str) – ON UPDATE 動作。
deferrable (str) – 控制強制約束的時間,例如
'INITIALLY DEFERRED'
。object_id_name (str) – 物件 ID 存取器的名稱。
lazy_load (bool) – 當外鍵欄位屬性被存取時(如果尚未載入),擷取相關的物件。如果停用此項,存取外鍵欄位將會回傳儲存在外鍵欄位中的值。
constraint_name (str) – (選用)用於外鍵約束的名稱。
用於儲存外鍵的欄位類別。
class User(Model): name = TextField() class Tweet(Model): user = ForeignKeyField(User, backref='tweets') content = TextField() # "user" attribute >>> some_tweet.user <User: charlie> # "tweets" backref attribute >>> for tweet in charlie.tweets: ... print(tweet.content) Some tweet Another tweet Yet another tweet
關於外鍵、聯結和模型之間關係的深入討論,請參閱關係與聯結。
注意
外鍵沒有特定的
field_type
,因為它們將根據所關聯模型的主鍵類型來決定其欄位類型。注意
如果您手動指定
field
,則該欄位必須是主鍵或具有唯一約束。注意
請小心 SQLite 中的外鍵。預設情況下,ON DELETE 不起作用,這可能會對您的資料庫完整性產生令人驚訝(且通常是不希望的)影響。即使您沒有指定
on_delete
也會影響您,因為預設的 ON DELETE 行為(在不修改資料的情況下失敗)不會發生,並且您的資料可能會在不知情的情況下被重新連結。最安全的方法是在實例化SqliteDatabase
時指定pragmas={'foreign_keys': 1}
。
- class DeferredForeignKey(rel_model_name[, **kwargs])
- 參數
rel_model_name (str) – 要參考的模型名稱。
用於表示延遲外鍵的欄位類別。適用於循環外鍵參照,例如:
class Husband(Model): name = TextField() wife = DeferredForeignKey('Wife', deferrable='INITIALLY DEFERRED') class Wife(Model): name = TextField() husband = ForeignKeyField(Husband, deferrable='INITIALLY DEFERRED')
在上面的例子中,當宣告
Wife
模型時,外鍵Husband.wife
會自動解析並轉換為常規的ForeignKeyField
。警告
當宣告和建立模型類別時,
DeferredForeignKey
參照會被解析。這表示如果您宣告一個指向已經匯入並建立的模型類別的DeferredForeignKey
,則延遲外鍵實例將永遠不會被解析。例如:class User(Model): username = TextField() class Tweet(Model): # This will never actually be resolved, because the User # model has already been declared. user = DeferredForeignKey('user', backref='tweets') content = TextField()
在這種情況下,您應該使用常規的
ForeignKeyField
或 您可以像這樣手動解析延遲外鍵:# Tweet.user will be resolved into a ForeignKeyField: DeferredForeignKey.resolve(User)
- class ManyToManyField(model[, backref=None[, through_model=None[, on_delete=None[, on_update=None]]]])
- 參數
ManyToManyField
提供了一個簡單的介面,用於處理多對多關係,其靈感來自 Django。多對多關係通常透過建立一個具有指向兩個相關模型的外鍵的聯結表來實現。例如,如果您正在為大學生建立課程大綱管理系統,則學生和課程之間的關係將是多對多的。以下是使用標準 API 的綱要:注意
這不是一個欄位,因為沒有與其相關的資料行。相反地,它提供了一個方便的介面,用於存取透過關聯模型相關的資料列。
宣告多對多關係的標準方式(不使用
ManyToManyField
):class Student(Model): name = CharField() class Course(Model): name = CharField() class StudentCourse(Model): student = ForeignKeyField(Student) course = ForeignKeyField(Course)
若要查詢特定學生的課程,您需要透過聯結表進行聯結:
# List the courses that "Huey" is enrolled in: courses = (Course .select() .join(StudentCourse) .join(Student) .where(Student.name == 'Huey')) for course in courses: print(course.name)
ManyToManyField
的設計宗旨是透過提供一個類似欄位的 API 來簡化這種使用案例,以查詢和修改聯結表中的資料。以下是我們使用ManyToManyField
的程式碼:class Student(Model): name = CharField() class Course(Model): name = CharField() students = ManyToManyField(Student, backref='courses')
注意
從 Peewee 的角度來看,
ManyToManyField
放在哪個模型上並不重要,因為反向參照只是鏡像。但是,為了編寫有效的 Python,您需要在第二個模型上新增ManyToManyField
,以便第一個模型的名稱位於範圍內。我們仍然需要一個聯結表來儲存學生和課程之間的關係。可以透過呼叫
get_through_model()
方法來存取此模型。這在建立表格時非常有用。# Create tables for the students, courses, and relationships between # the two. db.create_tables([ Student, Course, Course.students.get_through_model()])
當從模型實例存取時,
ManyToManyField
會公開一個代表相關物件集的ModelSelect
。讓我們使用互動式 Shell 來看看這一切是如何運作的:>>> huey = Student.get(Student.name == 'huey') >>> [course.name for course in huey.courses] ['English 101', 'CS 101'] >>> engl_101 = Course.get(Course.name == 'English 101') >>> [student.name for student in engl_101.students] ['Huey', 'Mickey', 'Zaizee']
若要在物件之間新增新的關係,您可以直接將物件指派給
ManyToManyField
屬性,或呼叫add()
方法。兩者之間的差異在於,簡單地指派將會清除任何現有的關係,而add()
可以保留現有的關係。>>> huey.courses = Course.select().where(Course.name.contains('english')) >>> for course in huey.courses.order_by(Course.name): ... print(course.name) English 101 English 151 English 201 English 221 >>> cs_101 = Course.get(Course.name == 'CS 101') >>> cs_151 = Course.get(Course.name == 'CS 151') >>> huey.courses.add([cs_101, cs_151]) >>> [course.name for course in huey.courses.order_by(Course.name)] ['CS 101', 'CS151', 'English 101', 'English 151', 'English 201', 'English 221']
這有相當多的課程,所以讓我們移除 200 級的英文課程。若要移除物件,請使用
remove()
方法。>>> huey.courses.remove(Course.select().where(Course.name.contains('2')) 2 >>> [course.name for course in huey.courses.order_by(Course.name)] ['CS 101', 'CS151', 'English 101', 'English 151']
若要從集合中移除所有關係,您可以使用
clear()
方法。假設 English 101 已取消,因此我們需要將所有學生從其中移除:>>> engl_101 = Course.get(Course.name == 'English 101') >>> engl_101.students.clear()
注意
如需使用標準 Peewee API 實作多對多關係的概述,請參閱實作多對多章節。對於除了最簡單的情況之外的所有情況,使用標準 API 實作多對多會更好。
- add(value[, clear_existing=True])
- 參數
value – 可以是
Model
實例、模型實例的列表或SelectQuery
。clear_existing (bool) – 是否移除現有的關係。
將
value
與目前實例關聯。您可以傳入單一模型實例、模型實例的列表,甚至是ModelSelect
。範例程式碼
# Huey needs to enroll in a bunch of courses, including all # the English classes, and a couple Comp-Sci classes. huey = Student.get(Student.name == 'Huey') # We can add all the objects represented by a query. english_courses = Course.select().where( Course.name.contains('english')) huey.courses.add(english_courses) # We can also add lists of individual objects. cs101 = Course.get(Course.name == 'CS 101') cs151 = Course.get(Course.name == 'CS 151') huey.courses.add([cs101, cs151])
- remove(value)
- 參數
value – 可以是
Model
實例、模型實例的列表或ModelSelect
。
將
value
從目前實例取消關聯。與add()
類似,您可以傳入模型實例、模型實例的列表,甚至是ModelSelect
。範例程式碼
# Huey is currently enrolled in a lot of english classes # as well as some Comp-Sci. He is changing majors, so we # will remove all his courses. english_courses = Course.select().where( Course.name.contains('english')) huey.courses.remove(english_courses) # Remove the two Comp-Sci classes Huey is enrolled in. cs101 = Course.get(Course.name == 'CS 101') cs151 = Course.get(Course.name == 'CS 151') huey.courses.remove([cs101, cs151])
- clear()
移除所有關聯的物件。
範例程式碼
# English 101 is canceled this semester, so remove all # the enrollments. english_101 = Course.get(Course.name == 'English 101') english_101.students.clear()
- get_through_model()
返回代表多對多連結表的
Model
。這可以在使用through_model
參數實例化欄位時手動指定。如果未指定through_model
,則會自動建立一個。當為使用
ManyToManyField
的應用程式建立資料表時,您必須明確建立 through table。# Get a reference to the automatically-created through table. StudentCourseThrough = Course.students.get_through_model() # Create tables for our two models as well as the through model. db.create_tables([ Student, Course, StudentCourseThrough])
- class DeferredThroughModel
在因為相依性而無法宣告模型或多對多欄位而導致 NameErrors 的情況下,作為 through-model 的佔位符。
範例
class Note(BaseModel): content = TextField() NoteThroughDeferred = DeferredThroughModel() class User(BaseModel): username = TextField() notes = ManyToManyField(Note, through_model=NoteThroughDeferred) # Cannot declare this before "User" since it has a foreign-key to # the User model. class NoteThrough(BaseModel): note = ForeignKeyField(Note) user = ForeignKeyField(User) # Resolve dependencies. NoteThroughDeferred.set_model(NoteThrough)
- class CompositeKey(*field_names)
- 參數
field_names – 組成主鍵的欄位名稱。
由多個欄位組成的複合主鍵。與其他欄位不同,複合鍵是在欄位定義後於模型的
Meta
類別中定義。它將要用作主鍵的欄位字串名稱作為參數。class BlogTagThrough(Model): blog = ForeignKeyField(Blog, backref='tags') tag = ForeignKeyField(Tag, backref='blogs') class Meta: primary_key = CompositeKey('blog', 'tag')
Schema Manager
- class SchemaManager(model[, database=None[, **context_options]])
-
提供管理給定模型的資料表和索引建立和刪除的方法。
- create_table([safe=True[, **options]])
- 參數
safe (bool) – 指定 IF NOT EXISTS 子句。
options – 任意選項。
為給定模型執行 CREATE TABLE 查詢。
- drop_table([safe=True[, drop_sequences=True[, **options]]])
- 參數
safe (bool) – 指定 IF EXISTS 子句。
drop_sequences (bool) – 刪除與資料表欄位相關聯的任何序列(僅限 postgres)。
options – 任意選項。
為給定模型執行 DROP TABLE 查詢。
- truncate_table([restart_identity=False[, cascade=False]])
- 參數
restart_identity (bool) – 重新啟動 ID 序列(僅限 postgres)。
cascade (bool) – 同時截斷相關資料表(僅限 postgres)。
為給定模型執行 TRUNCATE TABLE。如果資料庫是 Sqlite,而它不支援 TRUNCATE,則會執行等效的 DELETE 查詢。
- create_indexes([safe=True])
- 參數
safe (bool) – 指定 IF NOT EXISTS 子句。
為模型定義的索引執行 CREATE INDEX 查詢。
- drop_indexes([safe=True])
- 參數
safe (bool) – 指定 IF EXISTS 子句。
為模型定義的索引執行 DROP INDEX 查詢。
- create_foreign_key(field)
- 參數
field (ForeignKeyField) – 要新增的外鍵欄位約束。
為給定欄位新增外鍵約束。在大多數情況下,此方法不是必要的,因為外鍵約束是作為資料表建立的一部分而建立的。例外情況是當您使用
DeferredForeignKey
建立循環外鍵關係時。在這些情況下,必須先建立資料表,然後新增延遲外鍵的約束。class Language(Model): name = TextField() selected_snippet = DeferredForeignKey('Snippet') class Snippet(Model): code = TextField() language = ForeignKeyField(Language, backref='snippets') # Creates both tables but does not create the constraint for the # Language.selected_snippet foreign key (because of the circular # dependency). db.create_tables([Language, Snippet]) # Explicitly create the constraint: Language._schema.create_foreign_key(Language.selected_snippet)
如需更多資訊,請參閱有關 循環外鍵相依性 的文件。
警告
由於 SQLite 對變更現有資料表的支援有限,因此無法將外鍵約束新增至現有的 SQLite 資料表。
- create_all([safe=True[, **table_options]])
- 參數
safe (bool) – 是否指定 IF NOT EXISTS。
為模型建立序列、索引和資料表。
- drop_all([safe=True[, drop_sequences=True[, **options]]])
- 參數
safe (bool) – 是否指定 IF EXISTS。
drop_sequences (bool) – 刪除與資料表欄位相關聯的任何序列(僅限 postgres)。
options – 任意選項。
刪除模型及其相關索引的資料表。
模型
- class Metadata(model[, database=None[, table_name=None[, indexes=None[, primary_key=None[, constraints=None[, schema=None[, only_save_dirty=False[, depends_on=None[, options=None[, without_rowid=False[, strict_tables=False[, **kwargs]]]]]]]]]]]]])
- 參數
model (Model) – 模型類別。
database (Database) – 模型所綁定的資料庫。
table_name (str) – 指定模型的資料表名稱。
indexes (list) –
ModelIndex
物件的列表。primary_key – 模型的主鍵(僅在為
CompositeKey
或False
時指定,表示無主鍵)。constraints (list) – 資料表約束的列表。
schema (str) – 資料表存在的 schema。
only_save_dirty (bool) – 當呼叫
save()
時,只儲存已修改的欄位。options (dict) – 模型任意選項。
without_rowid (bool) – 指定 WITHOUT ROWID(僅限 SQLite)。
strict_tables (bool) – 指定 STRICT(僅限 SQLite,需要 3.37+ 版本)。
kwargs – 任意設定屬性和值。
儲存
Model
的元數據。這個類別不應該被直接實例化,而是使用
Model
類別的內部Meta
類別的屬性來實例化。然後,元數據屬性在Model._meta
上可用。- model_graph([refs=True[, backrefs=True[, depth_first=True]]])
- 參數
refs (bool) – 是否跟隨外鍵引用。
backrefs (bool) – 是否跟隨外鍵反向引用。
depth_first (bool) – 是否進行深度優先搜索(
False
表示廣度優先)。
遍歷模型圖並返回一個包含 3 元組的列表,包含
(外鍵欄位, 模型類別, 是否為反向引用)
。
- set_table_name(table_name)
- 參數
table_name (str) – 要將模型綁定的資料表名稱。
在運行時將模型類別綁定到給定的資料表名稱。
- class SubclassAwareMetadata
追蹤
Model
子類別的元數據子類別。當您需要追蹤專案中的所有模型時非常有用。範例
from peewee import SubclassAwareMetadata class Base(Model): class Meta: database = db model_metadata_class = SubclassAwareMetadata # Create 3 model classes that inherit from Base. class A(Base): pass class B(Base): pass class C(Base): pass # Now let's make a helper for changing the `schema` for each Model. def change_schema(schema): def _update(model): model._meta.schema = schema return _update # Set all models to use "schema1", e.g. "schema1.a", "schema1.b", etc. # Will apply the function to every subclass of Base. Base._meta.map_models(change_schema('schema1')) # Set all models to use "schema2", e.g. "schema2.a", "schema2.b", etc. Base._meta.map_models(change_schema('schema2'))
- map_models(fn)
將函數應用於所有子類別。
- class Model(**kwargs)
- 參數
kwargs – 將欄位名稱對應到值的映射,用於初始化模型。
模型類別為處理資料庫表提供高階抽象。模型與資料庫表(或類似表的物件,例如視圖)是一對一的映射。
Model
的子類別將任意數量的Field
實例宣告為類別屬性。這些欄位對應到表中的欄。表層級的操作,例如
select()
、update()
、insert()
和delete()
被實作為類別方法。列層級的操作,例如save()
和delete_instance()
被實作為實例方法。範例
db = SqliteDatabase(':memory:') class User(Model): username = TextField() join_date = DateTimeField(default=datetime.datetime.now) is_admin = BooleanField(default=False) admin = User(username='admin', is_admin=True) admin.save()
- classmethod alias([alias=None])
- 參數
alias (str) – 別名的可選名稱。
- 傳回
ModelAlias
實例。
建立模型類別的別名。模型別名允許您在查詢中多次引用同一個
Model
,例如在進行自我聯接或子查詢時。範例
Parent = Category.alias() sq = (Category .select(Category, Parent) .join(Parent, on=(Category.parent == Parent.id)) .where(Parent.name == 'parent category'))
- classmethod select(*fields)
- 參數
fields – 模型類別、欄位實例、函數或表達式的列表。如果沒有提供任何參數,則預設會選取給定模型的所有欄。
- 傳回
ModelSelect
查詢。
建立 SELECT 查詢。如果沒有明確提供欄位,則預設情況下查詢將選取模型上定義的所有欄位,除非您將查詢用作子查詢,在這種情況下預設只會選取主鍵。
選取所有欄的範例
query = User.select().where(User.active == True).order_by(User.username)
選取 Tweet 和父模型 User 上所有欄的範例。當在 Tweet 實例上存取
user
外鍵時,不需要額外的查詢(請參閱 N+1 以了解更多詳細資訊)query = (Tweet .select(Tweet, User) .join(User) .order_by(Tweet.created_date.desc())) for tweet in query: print(tweet.user.username, '->', tweet.content)
只選取主鍵的子查詢範例
inactive_users = User.select().where(User.active == False) # Here, instead of defaulting to all columns, Peewee will default # to only selecting the primary key. Tweet.delete().where(Tweet.user.in_(inactive_users)).execute()
- classmethod update([__data=None[, **update]])
- 參數
__data (dict) – 欄位對應到值的
dict
。update – 欄位名稱對應到值的映射。
建立 UPDATE 查詢。
顯示如果使用者的註冊過期,如何將其標記為非活動狀態的範例
q = (User .update({User.active: False}) .where(User.registration_expired == True)) q.execute() # Execute the query, returning number of rows updated.
顯示原子更新的範例
q = (PageView .update({PageView.count: PageView.count + 1}) .where(PageView.url == url)) q.execute() # Execute the query.
注意
當執行更新查詢時,將返回修改的列數。
- classmethod insert([__data=None[, **insert]])
- 參數
__data (dict) – 要插入的欄位對應到值的
dict
。insert – 欄位名稱對應值的映射。
建立一個 INSERT 查詢。
將新的資料列插入資料庫。如果模型上的任何欄位具有預設值,則當這些欄位未在
insert
字典中明確設定時,將使用這些值。顯示如何建立新用戶的範例
q = User.insert(username='admin', active=True, registration_expired=False) q.execute() # perform the insert.
您也可以使用
Field
物件作為鍵new_id = User.insert({User.username: 'admin'}).execute()
如果您的模型在其中一個欄位上有預設值,並且該欄位未在
insert
參數中指定,則會使用預設值class User(Model): username = CharField() active = BooleanField(default=True) # This INSERT query will automatically specify `active=True`: User.insert(username='charlie')
注意
當對具有自動遞增主鍵的表執行插入查詢時,將返回新資料列的主鍵。
- classmethod insert_many(rows[, fields=None])
- 參數
rows – 一個產生要插入之資料列的可迭代物件。
fields (list) – 要插入的欄位列表。
- 傳回
修改的資料列數(請參閱註解)。
插入多個資料列。
rows
參數必須是一個產生字典或元組的可迭代物件,其中元組值的順序對應於fields
引數中指定的欄位。與insert()
一樣,未在字典中指定的欄位將使用其預設值(如果存在)。注意
由於批次插入的性質,每個資料列必須包含相同的欄位。以下程式碼將無法運作
Person.insert_many([ {'first_name': 'Peewee', 'last_name': 'Herman'}, {'first_name': 'Huey'}, # Missing "last_name"! ]).execute()
插入多個使用者的範例
data = [ ('charlie', True), ('huey', False), ('zaizee', False)] query = User.insert_many(data, fields=[User.username, User.is_admin]) query.execute()
使用字典的等效範例
data = [ {'username': 'charlie', 'is_admin': True}, {'username': 'huey', 'is_admin': False}, {'username': 'zaizee', 'is_admin': False}] # Insert new rows. User.insert_many(data).execute()
由於
rows
參數可以是任意的可迭代物件,您也可以使用產生器def get_usernames(): for username in ['charlie', 'huey', 'peewee']: yield {'username': username} User.insert_many(get_usernames()).execute()
警告
如果您使用 SQLite,您的 SQLite 函式庫必須是 3.7.11 或更新的版本才能使用批次插入。
注意
SQLite 對每個語句的繫結變數有預設限制。此限制可以在編譯時或執行時修改,但是,如果在執行時修改,您只能指定一個低於預設限制的值。
如需更多資訊,請查看以下 SQLite 文件
注意
預設傳回值是修改的資料列數。但是,當使用 Postgres 時,Peewee 預設會傳回一個產生插入資料列主鍵的游標。若要停用 Postgres 的此功能,請使用
as_rowcount()
。
- classmethod insert_from(query, fields)
- 參數
query (Select) – 要用作資料來源的 SELECT 查詢。
fields – 要將資料插入其中的欄位。
- 傳回
修改的資料列數(請參閱註解)。
使用 SELECT 查詢作為來源來插入資料。此 API 應用於 INSERT INTO … SELECT FROM … 形式的查詢。
跨資料表插入資料以進行反正規化的範例
source = (User .select(User.username, fn.COUNT(Tweet.id)) .join(Tweet, JOIN.LEFT_OUTER) .group_by(User.username)) UserTweetDenorm.insert_from( source, [UserTweetDenorm.username, UserTweetDenorm.num_tweets]).execute()
注意
預設傳回值是修改的資料列數。但是,當使用 Postgres 時,Peewee 預設會傳回一個產生插入資料列主鍵的游標。若要停用 Postgres 的此功能,請使用
as_rowcount()
。
- classmethod replace([__data=None[, **insert]])
- 參數
__data (dict) – 要插入的欄位對應到值的
dict
。insert – 欄位名稱對應值的映射。
建立一個使用 REPLACE 進行衝突解決的 INSERT 查詢。
請參閱
Model.insert()
以取得範例。
- classmethod replace_many(rows[, fields=None])
- 參數
rows – 一個產生要插入之資料列的可迭代物件。
fields (list) – 要插入的欄位列表。
使用 REPLACE 進行衝突解決來插入多個資料列。
請參閱
Model.insert_many()
以取得範例。
- classmethod raw(sql, *params)
- 參數
sql (str) – 要執行的 SQL 查詢。
params – 查詢的參數。
直接執行 SQL 查詢。
從 User 資料表選取資料列的範例
q = User.raw('select id, username from users') for user in q: print(user.id, user.username)
注意
通常,
raw
的使用保留給那些您可以顯著最佳化選取查詢的情況。它對於選取查詢很有用,因為它將傳回模型的實例。
- classmethod delete()
建立 DELETE 查詢。
顯示刪除所有非使用中用戶的範例
q = User.delete().where(User.active == False) q.execute() # Remove the rows, return number of rows removed.
警告
此方法對整個資料表執行刪除。若要刪除單個實例,請參閱
Model.delete_instance()
。
- classmethod create(**query)
- 參數
query – 欄位名稱對應值的映射。
將新資料列插入資料表並傳回對應的模型實例。
顯示建立用戶的範例(將會將資料列加入資料庫)
user = User.create(username='admin', password='test')
注意
create() 方法是 instantiate-then-save 的簡寫。
- classmethod bulk_create(model_list[, batch_size=None])
- 參數
model_list (iterable) – 未儲存的
Model
實例的列表或其他可迭代物件。batch_size (int) – 每次插入批次的資料列數。如果未指定,則所有模型將在單個查詢中插入。
- 傳回
沒有傳回值。
有效率地將多個未儲存的模型實例插入資料庫。與
insert_many()
接受資料列資料作為字典或列表的列表不同,此方法接受未儲存的模型實例列表。範例
# List of 10 unsaved users. user_list = [User(username='u%s' % i) for i in range(10)] # All 10 users are inserted in a single query. User.bulk_create(user_list)
批次
user_list = [User(username='u%s' % i) for i in range(10)] with database.atomic(): # Will execute 4 INSERT queries (3 batches of 3, 1 batch of 1). User.bulk_create(user_list, batch_size=3)
警告
只有在使用 Postgresql(支援
RETURNING
子句)時,才會設定新建立模型的主鍵值。SQLite 通常對查詢的繫結參數有數量限制,因此最大批次大小應為參數限制 / 欄位數量。對於 Sqlite < 3.32.0,此限制通常為 999,而對於較新版本,則為 32766。
當提供批次大小時,強烈建議您使用
Database.atomic()
將呼叫包裝在交易或儲存點中。否則,批次中途發生錯誤可能會使資料庫處於不一致的狀態。
- classmethod bulk_update(model_list, fields[, batch_size=None])
- 參數
model_list (iterable) –
Model
實例的列表或其他可迭代物件。fields (list) – 要更新的欄位列表。
batch_size (int) – 每次插入批次的資料列數。如果未指定,則所有模型將在單個查詢中插入。
- 傳回
更新的資料列總數。
有效率地更新多個模型實例。
範例
# First, create 3 users. u1, u2, u3 = [User.create(username='u%s' % i) for i in (1, 2, 3)] # Now let's modify their usernames. u1.username = 'u1-x' u2.username = 'u2-y' u3.username = 'u3-z' # Update all three rows using a single UPDATE query. User.bulk_update([u1, u2, u3], fields=[User.username])
這將導致執行以下 SQL
UPDATE "users" SET "username" = CASE "users"."id" WHEN 1 THEN "u1-x" WHEN 2 THEN "u2-y" WHEN 3 THEN "u3-z" END WHERE "users"."id" IN (1, 2, 3);
如果您要更新大量物件,強烈建議您指定
batch_size
並將操作包裝在交易中with database.atomic(): User.bulk_update(user_list, fields=['username'], batch_size=50)
警告
SQLite 通常對查詢的繫結參數有數量限制。對於 Sqlite < 3.32.0,此限制通常為 999,而對於較新版本,則為 32766。
當提供批次大小時,強烈建議您使用
Database.atomic()
將呼叫包裝在交易或儲存點中。否則,批次中途發生錯誤可能會使資料庫處於不一致的狀態。
- classmethod get(*query, **filters)
- 參數
query – 零個或多個
Expression
物件。filters – 將欄位名稱對應到 Django 風格的篩選條件。
- 引發
DoesNotExist
- 傳回
符合指定篩選條件的模型實例。
檢索符合指定篩選條件的單個模型實例。如果沒有返回任何模型,則會引發
DoesNotExist
異常。user = User.get(User.username == username, User.active == True)
此方法也透過
SelectQuery
公開,但它不接受任何參數。active = User.select().where(User.active == True) try: user = active.where( (User.username == username) & (User.active == True) ).get() except User.DoesNotExist: user = None
注意
get()
方法是選擇限制為 1 的簡寫。它具有額外的行為,即在找不到匹配的列時引發異常。如果找到多個列,則會使用資料庫游標返回的第一列。
- classmethod get_or_none(*query, **filters)
與
Model.get()
相同,但如果沒有模型符合給定的篩選條件,則返回None
。
- classmethod get_by_id(pk)
- 參數
pk – 主鍵值。
呼叫
Model.get()
並指定依主鍵查找的簡寫。如果具有給定主鍵值的實例不存在,則會引發DoesNotExist
異常。範例
user = User.get_by_id(1) # Returns user with id = 1.
- classmethod set_by_id(key, value)
- 參數
key – 主鍵值。
value (dict) – 要更新的欄位到值的對應。
使用給定的主鍵更新資料的簡寫。如果沒有具有給定主鍵的列存在,則不會引發異常。
範例
# Set "is_admin" to True on user with id=3. User.set_by_id(3, {'is_admin': True})
- classmethod delete_by_id(pk)
- 參數
pk – 主鍵值。
刪除具有給定主鍵的列的簡寫。如果沒有具有給定主鍵的列存在,則不會引發異常。
- classmethod get_or_create(**kwargs)
- 參數
kwargs – 欄位名稱到值的對應。
defaults – 如果要建立新列時要使用的預設值。
- 傳回
由
Model
實例和布林值組成的元組,布林值指示是否已建立新物件。
嘗試獲取符合給定篩選條件的列。如果找不到匹配的列,則建立新列。
警告
使用此方法時,可能會發生競爭條件。
不使用
get_or_create
的範例# Without `get_or_create`, we might write: try: person = Person.get( (Person.first_name == 'John') & (Person.last_name == 'Lennon')) except Person.DoesNotExist: person = Person.create( first_name='John', last_name='Lennon', birthday=datetime.date(1940, 10, 9))
使用
get_or_create
的等效程式碼person, created = Person.get_or_create( first_name='John', last_name='Lennon', defaults={'birthday': datetime.date(1940, 10, 9)})
- classmethod filter(*dq_nodes, **filters)
- 參數
dq_nodes – 零個或多個
DQ
物件。filters – Django 風格的篩選條件。
- 傳回
ModelSelect
查詢。
- get_id()
- 傳回
模型實例的主鍵。
- save([force_insert=False[, only=None]])
- 參數
force_insert (bool) – 強制執行 INSERT 查詢。
only (list) – 僅儲存給定的
Field
實例。
- 傳回
已修改的列數。
儲存模型實例中的資料。預設情況下,主鍵值的存在將導致執行 UPDATE 查詢。
顯示儲存模型實例的範例
user = User() user.username = 'some-user' # does not touch the database user.save() # change is persisted to the db
- dirty_fields
傳回已修改的欄位清單。
- 回傳類型
list
注意
如果您只想持久化已修改的欄位,您可以呼叫
model.save(only=model.dirty_fields)
。如果您總是只想儲存模型的已變更欄位,您可以使用 Meta 選項
only_save_dirty = True
。然後,每當您呼叫Model.save()
時,預設情況下只會儲存已變更的欄位,例如:class Person(Model): first_name = CharField() last_name = CharField() dob = DateField() class Meta: database = db only_save_dirty = True
警告
Peewee 透過觀察欄位屬性在模型實例上設定的時間來判斷欄位是否「已變更」。如果欄位包含可變的值(例如字典實例),然後修改該字典,Peewee 將不會注意到此變更。
- is_dirty()
傳回布林值,指示是否有任何欄位是手動設定的。
- delete_instance([recursive=False[, delete_nullable=False]])
- 參數
recursive (bool) – 刪除相關模型。
delete_nullable (bool) – 刪除具有空值外鍵的相關模型。如果
False
,可為空的關聯將會設定為 NULL。
刪除給定的實例。任何設定為在刪除時聯級的外鍵都會自動刪除。為了進行更程式化的控制,您可以指定
recursive=True
,這將會刪除任何不可為空的相關模型 (那些可為空的模型將會設定為 NULL)。如果您希望刪除所有依賴項,無論它們是否可為空,請設定delete_nullable=True
。範例
some_obj.delete_instance() # it is gone forever
- classmethod bind(database[, bind_refs=True[, bind_backrefs=True]])
- 參數
database (Database) – 要繫結的資料庫。
bind_refs (bool) – 繫結相關的模型。
bind_backrefs (bool) – 繫結反向參照的相關模型。
將模型(和指定的關聯)繫結到給定的資料庫。
另請參閱:
Database.bind()
。
- classmethod bind_ctx(database[, bind_refs=True[, bind_backrefs=True]])
與
bind()
類似,但會傳回一個上下文管理器,該管理器僅在封裝區塊的持續時間內繫結模型。另請參閱:
Database.bind_ctx()
。
- classmethod table_exists()
- 傳回
指示表格是否存在的布林值。
- classmethod create_table([safe=True[, **options]])
- 參數
safe (bool) – 如果設定為
True
,則建立表格查詢將包含IF NOT EXISTS
子句。
建立模型表格、索引、約束條件和序列。
範例
with database: SomeModel.create_table() # Execute the create table query.
- classmethod drop_table([safe=True[, **options]])
- 參數
safe (bool) – 如果設定為
True
,建立表格的查詢將包含IF EXISTS
子句。
刪除模型表格。
- truncate_table([restart_identity=False[, cascade=False]])
- 參數
restart_identity (bool) – 重新啟動 ID 序列(僅限 postgres)。
cascade (bool) – 同時截斷相關資料表(僅限 postgres)。
截斷(刪除所有列)模型。
- classmethod index(*fields[, unique=False[, safe=True[, where=None[, using=None[, name=None]]]]])
- 參數
fields – 要建立索引的欄位。
unique (bool) – 索引是否為 UNIQUE。
safe (bool) – 是否加入 IF NOT EXISTS 子句。
where (Expression) – 索引的可選 WHERE 子句。
using (str) – 索引演算法。
name (str) – 可選的索引名稱。
在模型上宣告索引的表達式方法。封裝
ModelIndex
實例的宣告。範例
class Article(Model): name = TextField() timestamp = TimestampField() status = IntegerField() flags = BitField() is_sticky = flags.flag(1) is_favorite = flags.flag(2) # CREATE INDEX ... ON "article" ("name", "timestamp" DESC) idx = Article.index(Article.name, Article.timestamp.desc()) # Be sure to add the index to the model: Article.add_index(idx) # CREATE UNIQUE INDEX ... ON "article" ("timestamp" DESC, "flags" & 2) # WHERE ("status" = 1) idx = (Article .index(Article.timestamp.desc(), Article.flags.bin_and(2), unique=True) .where(Article.status == 1)) # Add index to model: Article.add_index(idx)
- classmethod add_index(*args, **kwargs)
- 參數
args –
ModelIndex
實例、要索引的欄位或包含建立索引之 SQL 的SQL
實例。kwargs – 傳遞至
ModelIndex
建構函式的關鍵字引數。
將索引新增至模型的定義。
注意
此方法實際上不會在資料庫中建立索引。相反地,它會將索引定義新增至模型的 metadata,以便後續呼叫
create_table()
將會建立新的索引(以及表格)。範例
class Article(Model): name = TextField() timestamp = TimestampField() status = IntegerField() flags = BitField() is_sticky = flags.flag(1) is_favorite = flags.flag(2) # CREATE INDEX ... ON "article" ("name", "timestamp") WHERE "status" = 1 idx = Article.index(Article.name, Article.timestamp).where(Article.status == 1) Article.add_index(idx) # CREATE UNIQUE INDEX ... ON "article" ("timestamp" DESC, "flags" & 2) ts_flags_idx = Article.index( Article.timestamp.desc(), Article.flags.bin_and(2), unique=True) Article.add_index(ts_flags_idx) # You can also specify a list of fields and use the same keyword # arguments that the ModelIndex constructor accepts: Article.add_index( Article.name, Article.timestamp.desc(), where=(Article.status == 1)) # Or even specify a SQL query directly: Article.add_index(SQL('CREATE INDEX ...'))
- dependencies([search_nullable=False])
- 參數
search_nullable (bool) – 搜尋透過可為 Null 的外鍵相關聯的模型
- 回傳類型
產生器表達式,產生查詢和外鍵欄位。
產生相依模型的查詢清單。產生包含查詢和相應外鍵欄位的 2 個元素的元組。對於搜尋模型的相依性很有用,例如:在刪除時會成為孤立的事物。
- __iter__()
- 傳回
給定類別的
ModelSelect
。
用於疊代模型的所有實例的便利函式。
範例
Setting.insert_many([ {'key': 'host', 'value': '192.168.1.2'}, {'key': 'port': 'value': '1337'}, {'key': 'user': 'value': 'nuggie'}]).execute() # Load settings from db into dict. settings = {setting.key: setting.value for setting in Setting}
- __len__()
- 傳回
表格中的列數。
範例
n_accounts = len(Account) # Is equivalent to: n_accounts = Account.select().count()
- class ModelAlias(model[, alias=None])
- 參數
model (Model) – 要參照的模型類別。
alias (str) – (選用)別名的名稱。
在查詢中提供模型的個別參照。
- class ModelSelect(model, fields_or_models)
- 參數
model (Model) – 要選取的模型類別。
fields_or_models – 要選取的欄位或模型類別清單。
SELECT 查詢的模型特定實作。
- switch([ctx=None])
- 參數
ctx –
Model
、ModelAlias
、子查詢或其他已聯結的物件。
切換聯結內容 - 後續對
join()
的呼叫所聯結的來源。用於指定對單一表格的多個聯結。如果未提供
ctx
,則會使用查詢的模型。以下範例從推文選取,並聯結使用者和推文標記
sq = Tweet.select().join(User).switch(Tweet).join(TweetFlag) # Equivalent (since Tweet is the query's model) sq = Tweet.select().join(User).switch().join(TweetFlag)
- objects([constructor=None])
- 參數
constructor – 建構函式(預設為傳回模型實例)
傳回使用給定建構函式建立的物件的結果列。預設行為是建立模型實例。
注意
當從多個來源/模型選取欄位資料時,可以使用此方法,使所有資料都可作為所查詢模型的屬性使用(而不是建構聯結的模型實例圖)。對於非常複雜的查詢,這可能會產生正面的效能影響,特別是疊代大型結果集時。
同樣地,您可以使用
dicts()
、tuples()
或namedtuples()
以達成更高的效能。
- join(dest[, join_type='INNER'[, on=None[, src=None[, attr=None]]]])
- 參數
dest – 要聯結的
Model
、ModelAlias
、Select
查詢或其他物件。join_type (str) – 聯結類型,預設為 INNER。
on – 聯結述詞或要聯結的
ForeignKeyField
。src – 明確指定聯結的來源。如果未指定,則會使用目前的聯結內容。
attr (str) – 從聯結的模型投影欄位時要使用的屬性。
與另一個類似表格的物件聯結。
聯結類型可以是下列其中之一
JOIN.INNER
JOIN.LEFT_OUTER
JOIN.RIGHT_OUTER
JOIN.FULL
JOIN.FULL_OUTER
JOIN.CROSS
選取推文並聯結使用者,以便僅限於由「管理員」使用者發佈的那些推文的範例
sq = Tweet.select().join(User).where(User.is_admin == True)
選取使用者並聯結特定外鍵欄位的範例。如需實際的使用範例,請參閱範例應用程式
sq = User.select().join(Relationship, on=Relationship.to_user)
關於外鍵、聯結和模型之間關係的深入討論,請參閱關係與聯結。
- join_from(src, dest[, join_type='INNER'[, on=None[, attr=None]]])
- 參數
src – 聯結的來源。
dest – 要聯結的表格。
使用與非模型特定
join()
相同的參數順序。透過要求指定聯結來源來略過聯結內容。
- filter(*args, **kwargs)
- 參數
args – 零個或多個
DQ
物件。kwargs – Django 樣式的關鍵字引數篩選條件。
使用 Django 樣式的篩選條件來表示 WHERE 子句。聯結之後可以鏈結外鍵欄位。支援的操作如下:
eq
- 等於ne
- 不等於lt
、lte
- 小於、小於或等於gt
、gte
- 大於、大於或等於in
- IN 值集is
- IS (例如 IS NULL)。like
、ilike
- LIKE 和 ILIKE (不區分大小寫)regexp
- 正則表達式符合
範例
# Get all tweets by user with username="peewee". q = Tweet.filter(user__username='peewee') # Get all posts that are draft or published, and written after 2023. q = Post.filter( (DQ(status='draft') | DQ(status='published')), timestamp__gte=datetime.date(2023, 1, 1))
- prefetch(*subqueries[, prefetch_type=PREFETCH_TYPE.WHERE])
- 參數
subqueries – 欲預先提取的
Model
類別或選擇查詢的列表。prefetch_type – 子查詢要使用的查詢類型。
- 傳回
返回一個已預先提取所選關聯的模型列表。
執行查詢,預先提取給定的額外資源。
預提取類型可以是以下其中之一:
PREFETCH_TYPE.WHERE
PREFETCH_TYPE.JOIN
另請參閱
prefetch()
獨立函式。範例
# Fetch all Users and prefetch their associated tweets. query = User.select().prefetch(Tweet) for user in query: print(user.username) for tweet in user.tweets: print(' *', tweet.content)
注意
由於
prefetch
必須重建模型的圖形,因此必須確保已選擇任何相關模型的外鍵/主鍵,以便正確映射相關物件。
- prefetch(sq, *subqueries[, prefetch_type=PREFETCH_TYPE.WHERE])
- 參數
sq – 作為起點使用的查詢。
subqueries – 一個或多個要積極提取的模型或
ModelSelect
查詢。prefetch_type – 子查詢要使用的查詢類型。
- 傳回
返回一個已預先提取所選關聯的模型列表。
積極提取相關物件,允許在存在一對多關係時有效率地查詢多個資料表。預提取類型會更改子查詢的建構方式,這可能會根據使用的資料庫引擎而有所需。
預提取類型可以是以下其中之一:
PREFETCH_TYPE.WHERE
PREFETCH_TYPE.JOIN
例如,有效率地查詢多對一的關係很簡單
query = (Tweet .select(Tweet, User) .join(User)) for tweet in query: # Looking up tweet.user.username does not require a query since # the related user's columns were selected. print(tweet.user.username, '->', tweet.content)
為了有效率地進行反向查詢,查詢使用者及其推文,您可以使用 prefetch
query = User.select() for user in prefetch(query, Tweet): print(user.username) for tweet in user.tweets: # Does not require additional query. print(' ', tweet.content)
注意
由於
prefetch
必須重建模型的圖形,因此必須確保已選擇任何相關模型的外鍵/主鍵,以便正確映射相關物件。
查詢建構器內部結構
- class AliasManager
管理在 SELECT 查詢中指派給
Source
物件的別名,以避免在單一查詢中使用多個來源時發生不明確的引用。- add(source)
將來源新增至 AliasManager 在目前範圍內的內部註冊表。別名將使用以下方案自動產生(其中每個縮排層級都表示一個新的範圍):
- 參數
source (Source) – 使管理員了解新的來源。如果已新增來源,則呼叫將不會執行任何操作。
- get(source[, any_depth=False])
傳回目前範圍內來源的別名。如果來源沒有別名,將會給予下一個可用的別名。
- 參數
source (Source) – 應該擷取其別名的來源。
- 傳回
已指派給來源的別名,或下一個可用的別名。
- 回傳類型
str
- push()
將新的範圍推送至堆疊。
- pop()
從堆疊中彈出範圍。
- class State(scope[, parentheses=False[, subquery=False[, **kwargs]]])
用於表示指定範圍內的狀態的輕量物件。在 SQL 產生期間,
Context
訪問的每個物件都可以檢查狀態。State
類別允許 Peewee 執行以下操作:使用欄位類型或 SQL 運算式的通用介面,但使用廠商特定的資料類型或運算子。
將
Column
執行個體編譯為完整限定的屬性、具名的別名等,具體取決於scope
的值。確保正確使用括號。
- 參數
scope (int) – 當狀態為活動狀態時要套用的範圍規則。
parentheses (bool) – 將包含的 SQL 包在括號中。
subquery (bool) – 目前狀態是否為外部查詢的子項。
kwargs (dict) – 應在目前狀態中套用的任意設定。
- class Context(**settings)
將 Peewee 結構轉換為參數化的 SQL 查詢。
Peewee 結構都應該實作一個 __sql__ 方法,此方法將在 SQL 產生期間由 Context 類別呼叫。__sql__ 方法接受單一參數,即 Context 執行個體,允許遞迴下降和檢視範圍與狀態。
- scope
傳回目前作用中的範圍規則。
- parentheses
傳回目前狀態是否包在括號中。
- subquery
傳回目前狀態是否為另一個查詢的子項。
- scope_normal([**kwargs])
預設範圍。來源由別名參照,欄由來源的點路徑參照。
- scope_source([**kwargs])
在定義來源時使用的範圍,例如在 SELECT 查詢的欄列表和 FROM 子句中。此範圍用於定義來源的完整限定名稱並指派別名。
- scope_values([**kwargs])
用於 UPDATE、INSERT 或 DELETE 查詢的範圍,在這些查詢中,我們不使用別名參照來源,而是直接參照來源。同樣地,由於只有一個資料表,因此不需要使用點路徑參照欄。
- scope_cte([**kwargs])
在產生通用資料表運算式的內容時使用的範圍。在 WITH 陳述式之後,在產生 CTE 的定義時使用(而不是僅僅參照一個 CTE)。
- scope_column([**kwargs])
在產生欄的 SQL 時使用的範圍。確保欄使用其正確的別名呈現。之所以需要此範圍,是因為在參照子選取中的內部投影時,Peewee 會將完整的 SELECT 查詢呈現為欄的「來源」(而不是查詢的別名 + . + 欄)。此範圍允許我們在只需要別名時,避免呈現完整的查詢。
- sql(obj)
將可組合的節點物件、子內容或其他物件附加到查詢 AST。Python 值(例如整數、字串、浮點數等)會被視為參數化的值。
- 傳回
已更新的 Context 物件。
- literal(keyword)
將字串文字附加到目前的查詢 AST。
- 傳回
已更新的 Context 物件。
- parse(node)
- 參數
node (Node) – 節點子類的執行個體。
- 傳回
包含 (sql, parameters) 的 2 元組。
將給定的節點轉換為 SQL AST,並傳回包含 SQL 查詢和參數的 2 元組。
- query()
- 傳回
一個包含 (sql, 參數) 的 2 元組,用於表示上下文。
常數與輔助函式
- class Proxy
為另一個物件建立一個代理或佔位符。
- initialize(obj)
- 參數
obj – 要代理的物件。
將代理綁定到給定的物件。之後,對代理的所有屬性查找和方法調用都將發送到給定的物件。
任何已註冊的回調都將被調用。
- attach_callback(callback)
- 參數
callback – 一個接受單一參數的函數,即綁定的物件。
- 傳回
self
新增一個回調,以便在代理初始化時執行。
- chunked(iterable, n)
- 參數
iterable – 一個可迭代的物件,是分塊資料的來源。
n (int) – 分塊大小
- 傳回
一個新的可迭代物件,產生來源資料的 n 長度區塊。
將大型資料清單分成較小區塊的有效率實作。
用法
it = range(10) # An iterable that yields 0...9. # Break the iterable into chunks of length 4. for chunk in chunked(it, 4): print(', '.join(str(num) for num in chunk)) # PRINTS: # 0, 1, 2, 3 # 4, 5, 6, 7 # 8, 9