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 – 当创建连接时传递给数据库驱动程序的任意关键字参数,例如 passwordhost 等。

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 – 当创建连接时传递给数据库驱动程序的任意关键字参数,例如 passwordhost 等。

初始化一个延迟数据库。有关更多信息,请参阅 运行时数据库配置

__enter__()

Database 实例可以用作上下文管理器,在这种情况下,连接将在包装块的持续时间内保持打开状态。

此外,在包装块内执行的任何 SQL 都将在事务中执行。

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

引发

OperationalError 如果连接已打开且 reuse_if_open 未设置为 True

打开与数据库的连接。

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() 也可以用作装饰器。

特定于数据库的参数

PostgresqlDatabaseMySQLDatabase 接受一个 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([...])

创建一个上下文管理器,该管理器在事务中运行包装块中的所有查询。

特定于数据库的参数

PostgresqlDatabaseMySQLDatabase 接受一个 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) – 将被生成的项目的迭代器。

  • 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])
参数

为给定的模型列表创建表、索引和相关元数据。

解析依赖项,以便按适当的顺序创建表。

drop_tables(models[, **options])
参数

删除给定的模型列表的表、索引和相关元数据。

解析依赖项,以便按适当的顺序删除表。

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 表示任何数量。

  • 确定性 (bool) – 函数对于给定输入是否确定性(这需要在索引中使用该函数)。需要 Sqlite 3.20 或更高版本,以及 sqlite3 驱动程序支持(在 Python 3.8 中添加到标准库)。

注册用户定义的标量函数。每次打开新连接时都会注册该函数。此外,如果连接已打开,则该函数将与打开的连接一起注册。

func([name=None[, num_params=-1[, deterministic=None]]])
参数
  • name (str) – 函数的名称(默认为函数名称)。

  • num_params (int) – 函数接受的参数数量,或 -1 表示任意数量。

  • 确定性 (bool) – 函数对于给定输入是否确定性(这需要在索引中使用该函数)。需要 Sqlite 3.20 或更高版本,以及 sqlite3 驱动程序支持(在 Python 3.8 中添加到标准库)。

装饰器,用于注册用户定义的标量函数。

示例

@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”的“魔术”属性,它是一个用于列/属性查找的工厂,例如

User = Table('users')
query = (User
         .select(User.c.username)
         .where(User.c.active == True)
         .order_by(User.c.username))
alias(name)

返回应用了给定别名的对象的副本。

select(*columns)
参数

columnsColumn 实例、表达式、函数、子查询或任何其他您想选择的内容。

在表上创建一个 Select 查询。如果表显式声明列并且没有提供列,则默认情况下将选择表的所有定义的列。

join(dest[, join_type='INNER'[, on=None]])
参数
  • dest (Source) – 将表与给定的目标联接。

  • join_type (str) – 联接类型。

  • on – 用作联接谓词的表达式。

返回值

一个 Join 实例。

联接类型可以是以下之一

  • JOIN.INNER

  • JOIN.LEFT_OUTER

  • JOIN.RIGHT_OUTER

  • JOIN.FULL

  • JOIN.FULL_OUTER

  • JOIN.CROSS

left_outer_join(dest[, on=None])
参数
  • dest (Source) – 将表与给定的目标联接。

  • on – 用作联接谓词的表达式。

返回值

一个 Join 实例。

使用 LEFT OUTER 联接调用 join() 的便捷方法。

class BaseTable

表类对象的基类,支持通过运算符重载进行联接。

__and__(dest)

dest 执行 INNER 联接。

__add__(dest)

dest 执行 LEFT OUTER 联接。

__sub__(dest)

dest 执行 RIGHT OUTER 联接。

__or__(dest)

dest 执行 FULL OUTER 联接。

__mul__(dest)

dest 执行 CROSS 联接。

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])
参数

databaseDatabase 对象。

将此表绑定到给定的数据库(或通过留空来取消绑定)。

当表绑定到数据库时,可以对它执行查询,而无需在查询的执行方法中指定数据库。

bind_ctx([database=None])
参数

databaseDatabase 对象。

返回一个上下文管理器,它将在包装块的持续时间内将表绑定到给定的数据库。

select(*columns)
参数

columnsColumn 实例、表达式、函数、子查询或任何其他您想选择的内容。

在表上创建一个 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 查询到表中。

replace([insert=None[, columns=None[, **kwargs]]])
参数
  • insert – 将列映射到值的字典,生成字典的可迭代对象(即列表),或 Select 查询。

  • columns (list) – 当插入的数据不是字典时,要插入的列列表。

  • kwargs – 列名到值的映射。

创建一个 Insert 查询到表中,其冲突解决方法是替换。

update([update=None[, **kwargs]])
参数
  • update – 将列映射到值的字典。

  • kwargs – 列名到值的映射。

创建一个 Update 查询到表中。

delete()

创建一个 Delete 查询到表中。

class Join(lhs, rhs[, join_type=JOIN.INNER[, on=None[, alias=None]]])

表示两个表状对象之间的 JOIN。

参数
  • lhs – 连接的左侧。

  • rhs – 连接的右侧。

  • join_type – 连接类型。例如 JOIN.INNER、JOIN.LEFT_OUTER 等。

  • on – 描述连接谓词的表达式。

  • alias (str) – 应用于连接数据的别名。

on(predicate)
参数

predicate (Expression) – 连接谓词。

指定用于此连接的谓词表达式。

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 的名称。

  • querySelect 描述 CTE 的查询。

  • recursive (bool) – CTE 是否是递归的。

  • columns (list) – CTE 生成的显式列列表(可选)。

select_from(*columns)

创建一个 SELECT 查询,该查询使用给定的公用表表达式作为新查询的源。

参数

columns – 从 CTE 中选择的列。

返回值

Select 使用公用表表达式的查询

union_all(other)

用于基本情况 CTE 以构造 CTE 的递归项。

参数

other – 递归项,通常是 Select 查询。

返回值

一个递归 CTE,具有给定的递归项。

class ColumnBase

类似列对象的基类,属性或表达式。

类似列的对象可以使用各种运算符和特殊方法进行组合。

  • &: 逻辑 AND

  • |: 逻辑 OR

  • +: 加法

  • -: 减法

  • *: 乘法

  • /: 除法

  • ^: 异或

  • ==: 等于

  • !=: 不等于

  • >: 大于

  • <: 小于

  • >=: 大于或等于

  • <=: 小于或等于

  • <<: IN

  • >>: IS (例如 IS NULL)

  • %: LIKE

  • **: ILIKE

  • bin_and(): 二进制 AND

  • bin_or(): 二进制 OR

  • in_(): IN

  • not_in(): NOT IN

  • regexp(): REGEXP

  • is_null(True/False): IS NULLIS NOT NULL

  • contains(s): LIKE %s%

  • startswith(s): LIKE s%

  • endswith(s): LIKE %s

  • between(low, high): BETWEEN low AND high

  • concat(): ||

alias(alias)
参数

alias (str) – 给定列状对象的别名。

返回值

一个 Alias 对象。

指示应给定列状对象指定的别名。

cast(as_type)
参数

as_type (str) – 要转换到的类型名称。

返回值

一个 Cast 对象。

创建一个 CAST 表达式。

asc([collation=None[, nulls=None]])
参数
  • collation (str) – 用于排序的排序规则名称。

  • nulls (str) – 排序空值(FIRST 或 LAST)。

返回值

一个用于该列的升序 Ordering 对象。

desc([collation=None[, nulls=None]])
参数
  • collation (str) – 用于排序的排序规则名称。

  • nulls (str) – 排序空值(FIRST 或 LAST)。

返回值

一个用于该列的降序 Ordering 对象。

__invert__()
返回值

一个用于该列的 Negated 包装器。

class Column(source, name)
参数
  • source (Source) – 列的来源。

  • name (str) – 列名。

表上的列或子查询返回的列。

class Alias(node, alias)
参数
  • node (Node) – 列状对象。

  • alias (str) – 要分配给列的别名。

为给定的列状对象创建一个命名别名。

alias([alias=None])
参数

alias (str) – 赋予别名列的新名称(或 None)。

为别名列状对象创建一个新的 Alias。如果新别名为 None,则返回原始列状对象。

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) – 用于排序的排序规则名称。

Asc(node[, collation=None[, nulls=None]])

用于实例化升序 Ordering 对象的简写。

Desc(node[, collation=None[, nulls=None]])

用于实例化降序 Ordering 对象的简写。

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]]]]]])
参数
  • partition_by (list) – 要按其进行分区的列列表。

  • order_by (list) – 要按其对窗口进行排序的列/表达式列表。

  • start – 一个 SQL 实例或表示窗口范围开始的字符串。

  • end – 一个 SQL 实例或表示窗口范围结束的字符串。

  • frame_type (str) – Window.RANGEWindow.ROWSWindow.GROUPS

  • window (Window) – 一个 Window 实例。

  • exclude – 帧排除,Window.CURRENT_ROWWindow.GROUPWindow.TIESWindow.NO_OTHERS 之一。

注意

有关使用 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 表达式用于确定哪些行被馈送到聚合函数。此 SQL 功能受 Postgres 和 SQLite 支持。

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__ 钩子,为调用 SQL 函数提供了一个不错的 API。

要创建表示 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.RANGEWindow.ROWSWindow.GROUPS

  • extends – 要扩展的 Window 定义。或者,您可以指定窗口的别名。

  • exclude – 帧排除,Window.CURRENT_ROWWindow.GROUPWindow.TIESWindow.NO_OTHERS 之一。

  • alias (str) – 窗口的别名。

表示 WINDOW 子句。

注意

有关使用 Peewee 的窗口函数的深入指南,请参阅 窗口函数 部分。

RANGE
ROWS
GROUPS

指定窗口 frame_type。请参阅 帧类型:RANGE vs ROWS vs 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()

指定帧类型。

extends([window=None])
参数

window (Window) – 要扩展的 Window 定义。或者,您可以指定窗口的别名。

exclude([frame_exclusion=None])
参数

frame_exclusion – 帧排除,可以是 Window.CURRENT_ROWWindow.GROUPWindow.TIESWindow.NO_OTHERS

alias([alias=None])
参数

alias (str) – 用于窗口的别名。

Case(predicate, expression_tuples[, default=None]])
参数
  • predicate – CASE 查询的谓词(可选)。

  • expression_tuples – 一个或多个要评估的 case。

  • 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 包含在括号中。

表示节点列表、多部分子句、参数列表等。

CommaNodeList(nodes)
参数

nodes (list) – 零个或多个节点。

返回值

一个 NodeList

表示由逗号连接的节点列表。

EnclosedNodeList(nodes)
参数

nodes (list) – 零个或多个节点。

返回值

一个 NodeList

表示由逗号连接并包含在括号中的节点列表。

class DQ(**query)
参数

query – 使用 Django 风格查找的任意过滤器表达式。

表示可组合的 Django 风格过滤器表达式,适合与 Model.filter()ModelSelect.filter() 方法一起使用。

class Tuple(*args)

表示 SQL 行值。行值受大多数数据库支持。

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 – 将列名映射到新值的字典。

The update() 方法支持使用列到值的字典或表示相同内容的关键字参数调用。

where(*expressions)
参数

expressions – 限制冲突解决子句操作的表达式。

conflict_target(*constraints)
参数

constraints – 用作冲突解决目标的列。

conflict_where(*expressions)
参数

expressions – 匹配冲突目标索引的表达式,如果冲突目标是部分索引。

conflict_constraint(constraint)
参数

constraint (str) – 用作冲突解决目标的约束名称。目前仅受 Postgres 支持。

class EXCLUDED

辅助对象,公开 EXCLUDED 命名空间,该命名空间与 INSERT ... ON CONFLICT 一起使用,用于引用冲突数据中的值。这是一个“神奇”的助手,因此可以通过访问其上与特定列相对应的属性来使用它。

示例

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
bind([database=None])
参数

database (Database) – 要执行查询的数据库。

将查询绑定到给定的数据库以执行。

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 (Database) – 要执行查询的数据库。如果查询之前已绑定到数据库,则不需要。

执行查询并返回结果(取决于正在执行的查询类型)。例如,选择查询的返回结果将是查询结果的迭代器。

iterator([database=None])
参数

database (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 – 一个或多个用于排序的类似 Column 的对象。

定义 ORDER BY 子句。任何之前指定的 value 将被覆盖。

order_by_extend(*values)
参数

values – 一个或多个用于排序的类似 Column 的对象。

使用给定的 value 扩展之前指定的任何 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 查询辅助类,它实现了运算符重载,用于创建复合查询。

select_from(*columns)
参数

columns – 从内部查询中选择的列。

返回值

一个包装调用查询的新查询。

创建一个包装当前(调用)查询的新查询。例如,假设您有一个简单的 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"

The 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

SelectCompoundSelect 查询的基类。

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) – 将结果作为元组返回?

  • as_dict (bool) – 将结果作为字典返回?

返回值

单个标量值。如果 as_tuple = True,则返回行元组。如果 as_dict = True,则返回行字典。

从结果集的第一行返回一个标量值。如果预期多个标量值(例如,单个查询中的多个聚合),则可以指定 as_tuple=True 以获取行元组。

示例

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}
count(database[, clear_limit=False])
参数
  • database (Database) – 要执行查询的数据库。

  • clear_limit (bool) – 在计数时清除任何 LIMIT 子句。

返回值

查询结果集中的行数。

返回查询结果集中的行数。

通过运行 SELECT COUNT(1) FROM (<当前查询>) 实现。

exists(database)
参数

database (Database) – 要执行查询的数据库。

返回值

当前查询是否存在任何结果。

返回一个布尔值,指示当前查询是否存在任何结果。

get(database)
参数

database (Database) – 要执行查询的数据库。

返回值

数据库中的单行或 None

执行查询并返回第一行(如果存在)。多次调用将导致执行多次查询。

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 查询上链接方法。

从数据库中选择一些用户实例的示例。仅选择 idusername 列。迭代时,将返回 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.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 – 要分组的零个或多个 Column 状对象。

定义 GROUP BY 子句。任何先前指定的 value 将被覆盖。

此外,要指定给定表上的所有列,可以将表/模型对象传递给单个列。

示例

query = (User
         .select(User, fn.Count(Tweet.id).alias('count'))
         .join(Tweet)
         .group_by(User))
group_by_extend(*columns)
参数

values – 要分组的零个或多个 Column 状对象。

使用给定的列扩展 GROUP BY 子句。

having(*expressions)
参数

expressions – 要包含在 HAVING 子句中的零个或多个表达式。

将给定的表达式包含在查询的 HAVING 子句中。这些表达式将与任何先前指定的 HAVING 表达式进行 AND 操作。

distinct(*columns)
参数

columns – 零个或多个列状对象。

指示此查询是否应使用 DISTINCT 子句。通过指定单个 True 值,查询将使用简单的 SELECT DISTINCT。指定一个或多个列将导致 SELECT DISTINCT ON。

window(*windows)
参数

windows – 零个或多个 Window 对象。

定义 WINDOW 子句。任何先前指定的 value 将被覆盖。

示例

# 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) – 一个或多个 TableModel、查询或 ValuesList,用于连接。

使用 UPDATE … FROM 语法指定要连接的额外表格,该语法受 Postgres 支持。 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 – 字典、列表或查询。

  • 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) – 要创建索引的模型类。

  • 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)

Fields

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'。

模型上的字段类似于表上的列。

field_type = '<some field type>'

用于将此字段映射到列类型的属性,例如“INT”。有关更多信息,请参阅源代码中的 FIELD 对象。

column

检索对底层 Column 对象的引用。

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 时使用 AutoIncrementFieldpragmas=[('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) – 自动舍入值。

  • 舍入

    默认为 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 位是否设置。

__getitem__(idx)

is_set() 相同

__setitem__(idx, value)

idx 处的位设置为值(True 或 False)。

__delitem__(idx)

clear_bit() 相同

__len__()

返回位图的长度(以字节为单位)。

__iter__()

返回一个迭代器,为位图中的每个位生成 1 或 0。

__and__(other)
参数

otherBigBitFieldbytesbytearraymemoryview 对象。

返回值

两个位图的按位 and

__or__(other)
参数

otherBigBitFieldbytesbytearraymemoryview 对象。

返回值

两个位图的按位 or

__xor__(other)
参数

otherBigBitFieldbytesbytearraymemoryview 对象。

返回值

两个位图的按位 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) – 年、月、日、时、分或秒。

返回值

表达式节点,用于将日期/时间截断到给定的分辨率。

将列中的值截断到给定的部分。此方法对于查找给定月份内的所有行很有用,例如。

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()

参见 DateTimeField.to_timestamp().

truncate(date_part)

参见 DateTimeField.truncate()。请注意,对于 DateField,只有 yearmonthday 有意义。

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,则时间戳使用秒分辨率存储。介于 26 之间的分辨率被视为小数位数,例如 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) – 要引用的模型,如果声明自引用外键,则为字符串“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]]]])
参数
  • model (Model) – 要创建关系的模型。

  • backref (str) – 反向引用的访问器名称

  • through_model (Model) – 用于中间表的 Model。如果未提供,将自动创建一个简单的中间表。

  • on_delete (str) – ON DELETE 操作,例如 'CASCADE'。将用于中间模型中的外键。

  • on_update (str) – ON UPDATE 操作。将用于中间模型中的外键。

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() 方法。假设英语 101 被取消,因此我们需要从其中删除所有学生

>>> engl_101 = Course.get(Course.name == 'English 101')
>>> engl_101.students.clear()

注意

有关使用标准 Peewee API 实现多对多关系的概述,请查看 实现多对多 部分。对于除最简单的用例之外的所有情况,最好使用标准 API 实现多对多关系。

through_model

表示多对多连接表的 Model。如果未显式声明,将自动生成。

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 的应用程序创建表时,必须显式创建中间表

# 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 的情况下声明模型或多对多字段的情况下,用于中间模型的占位符。

示例

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]])
参数
  • model (Model) – 模型类。

  • database (Database) – 如果未指定,则默认为 model._meta.database。

提供用于管理给定模型的表和索引的创建和删除的方法。

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_sequence(field)
参数

field (Field) – 指定序列的字段实例。

为给定的 Field 创建序列。

drop_sequence(field)
参数

field (Field) – 指定序列的字段实例。

删除给定的 Field 的序列。

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 – 任意选项。

删除模型的表和关联的索引。

Model

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 – 模型的主键(仅在它是 CompositeKeyFalse 表示没有主键时指定)。

  • constraints (list) – 表约束列表。

  • schema (str) – 表所在的模式。

  • 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 上使用。

table

返回对底层 Table 对象的引用。

model_graph([refs=True[, backrefs=True[, depth_first=True]]])
参数
  • refs (bool) – 跟踪外键引用。

  • backrefs (bool) – 跟踪外键反向引用。

  • depth_first (bool) – 进行深度优先搜索(False 表示广度优先)。

遍历模型图并返回一个包含 3 元组的列表,每个元组包含 (foreign key field, model class, is_backref)

set_database(database)
参数

database (Database) – 要绑定模型的数据库对象。

将模型类绑定到给定的 Database 实例。

警告

此 API 不应需要使用。相反,要更改运行时 Model 的数据库,请使用以下方法之一

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 类为使用数据库表提供了一个高级抽象。模型与数据库表(或类似表的对象,例如视图)之间是一对一映射。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 查询。如果未明确提供任何字段,则查询默认情况下将 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 – 字段名到值的映射。

创建一个 INSERT 查询,使用 REPLACE 进行冲突解决。

有关示例,请参见 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() 方法是实例化然后保存的简写。

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)
参数
  • argsModelIndex 实例、要索引的字段或包含用于创建索引的 SQL 的 SQL 实例。

  • kwargs – 传递给 ModelIndex 构造函数的关键字参数。

将索引添加到模型的定义中。

注意

此方法实际上不会在数据库中创建索引。相反,它将索引定义添加到模型的元数据中,以便后续对 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) – 搜索通过可空外键关联的模型

返回类型

生成器表达式,生成查询和外键字段。

生成依赖模型的查询列表。生成包含查询和对应外键字段的 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])
参数

ctxModelModelAlias、子查询或其他已连接的对象。

切换连接上下文 - 后续对 join() 的调用将针对其进行连接。用于指定针对单个表的多个连接。

如果未提供 ctx,则将使用查询的模型。

以下示例从 tweet 中选择并连接到 user 和 tweet-flag

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]]]])
参数
  • destModelModelAliasSelect 查询或其他要连接的对象。

  • join_type (str) – 连接类型,默认为 INNER。

  • on – 连接谓词或要连接的 ForeignKeyField

  • src – 显式指定连接的源。如果未指定,则将使用当前连接上下文

  • attr (str) – 从已连接模型中投影列时要使用的属性。

与另一个表状对象连接。

联接类型可以是以下之一

  • JOIN.INNER

  • JOIN.LEFT_OUTER

  • JOIN.RIGHT_OUTER

  • JOIN.FULL

  • JOIN.FULL_OUTER

  • JOIN.CROSS

示例选择 tweet 并连接到 user 以限制为仅由“admin”用户发出的 tweet

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 - 在值集中

  • 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

管理分配给 Source 对象的别名,以避免在单个查询中使用多个源时出现不明确的引用。

add(source)

将源添加到 AliasManager 的内部注册表中的当前范围。别名将使用以下方案自动生成(其中每个缩进级别表示一个新范围)

参数

source (Source) – 使管理器了解新的源。如果源已添加,则调用将是无操作。

get(source[, any_depth=False])

返回当前范围中源的别名。如果源没有别名,它将被赋予下一个可用的别名。

参数

source (Source) – 应该检索其别名的源。

返回值

已分配给源的别名,或下一个可用的别名。

返回类型

str

__setitem__(source, alias)

手动设置当前范围中源的别名。

参数

source (Source) – 我们为其设置别名的源。

push()

将新范围推送到堆栈。

pop()

从堆栈中弹出范围。

class State(scope[, parentheses=False[, subquery=False[, **kwargs]]])

用于表示给定范围状态的轻量级对象。在 SQL 生成期间, Context 访问的每个对象都可以检查状态。 State 类允许 Peewee 执行以下操作

  • 对字段类型或 SQL 表达式使用通用接口,但使用特定于供应商的数据类型或运算符。

  • 根据 scope 的值,将 Column 实例编译为完全限定的属性,作为命名别名等。

  • 确保括号的使用适当。

参数
  • 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)

将可组合的 Node 对象、子上下文或其他对象追加到查询 AST。Python 值(如整数、字符串、浮点数等)被视为参数化值。

返回值

更新的 Context 对象。

literal(keyword)

将字符串文字追加到当前查询 AST。

返回值

更新的 Context 对象。

parse(node)
参数

node (Node) – Node 子类的实例。

返回值

由 (sql, parameters) 组成的 2 元组。

将给定节点转换为 SQL AST 并返回由 SQL 查询和参数组成的 2 元组。

query()
返回值

由 (sql, parameters) 组成的 2 元组,用于上下文。

常量和助手

class Proxy

为另一个对象创建代理或占位符。

initialize(obj)
参数

obj – 要代理的对象。

将代理绑定到给定对象。之后,对代理的所有属性查找和方法调用都将发送到给定对象。

将调用已注册的任何回调。

attach_callback(callback)
参数

callback – 一个接受单个参数(绑定对象)的函数。

返回值

self

添加一个回调,在代理初始化时执行。

class DatabaseProxy

代理子类,适合用作 Database 实例的占位符。

有关用法的详细信息,请参见 动态定义数据库

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