【Python百日进阶-Web开发-Peewee】Day252 - Peewee 创建模型表、索引和约束

7.2 创建模型表

为了开始使用我们的模型,必须先打开与数据库的连接并创建表。Peewee 将运行必要的CREATE TABLE查询,另外创建任何约束和索引。

# Connect to our database.
db.connect()

# Create the tables.
db.create_tables([User, Tweet])

笔记

严格来说,没有必要调用connect() ,但明确的做法是很好的做法。这样,如果出现问题,错误会发生在连接步骤,而不是稍后的某个任意时间。

笔记

默认情况下,Peewee在创建表时包含一个子句。如果要禁用此功能,请指定.IF NOT EXISTSsafe=False

创建表后,如果您选择修改数据库架构(通过添加、删除或以其他方式更改列),您将需要:

  • 删除表并重新创建它。
  • 运行一个或多个ALTER TABLE查询。Peewee 带有一个模式迁移工具,可以大大简化这个过程。检查架构迁移 文档以获取详细信息。

7.3 模型选项和表元数据

为了不污染模型命名空间,模型特定的配置被放置在一个名为Meta的特殊类中(从 django 框架借用的约定):

from peewee import *

contacts_db = SqliteDatabase('contacts.db')

class Person(Model):
    name = CharField()

    class Meta:
        database = contacts_db

这指示 peewee 每当对Person执行查询时使用联系人数据库。

笔记

看一下示例模型- 您会注意到我们创建了一个BaseModel定义数据库的模型,然后对其进行了扩展。这是定义数据库和创建模型的首选方式。

定义类后,您不应访问ModelClass.Meta,而应使用ModelClass._meta:

>>> Person.Meta
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'Person' has no attribute 'Meta'

>>> Person._meta
<peewee.ModelOptions object at 0x7f51a2f03790>

该类ModelOptions实现了几种可用于检索模型元数据的方法(例如字段列表、外键关系等)。

>>> Person._meta.fields
{'id': <peewee.AutoField object at 0x7f51a2e92750>,
 'name': <peewee.CharField object at 0x7f51a2f0a510>}

>>> Person._meta.primary_key
<peewee.AutoField object at 0x7f51a2e92750>

>>> Person._meta.database
<peewee.SqliteDatabase object at 0x7f519bff6dd0>

您可以将多个选项指定为Meta属性。虽然大多数选项是可继承的,但有些是特定于表的,不会被子类继承。

选项意义可继承?
database模型数据库是的
table_name存储数据的表名
table_function动态生成表名的函数是的
indexes要索引的字段列表是的
primary_key一个CompositeKey实例是的
constraints表约束列表是的
schema模型的数据库模式是的
only_save_dirty调用model.save()时,只保存脏字段是的
options创建表扩展的选项字典是的
table_settings右括号后的设置字符串列表是的
temporary表示临时表是的
legacy_table_names使用旧表名生成(默认启用)是的
depends_on表示此表依赖于另一个创建
without_rowid指示表不应有 rowid(仅限 SQLite)
strict_tables指示严格的数据类型(仅限 SQLite,3.37+)是的
这是一个显示可继承与不可继承属性的示例:
>>> db = SqliteDatabase(':memory:')
>>> class ModelOne(Model):
...     class Meta:
...         database = db
...         table_name = 'model_one_tbl'
...
>>> class ModelTwo(ModelOne):
...     pass
...
>>> ModelOne._meta.database is ModelTwo._meta.database
True
>>> ModelOne._meta.table_name == ModelTwo._meta.table_name
False

7.3.1 Meta.primary_key

该Meta.primary_key属性用于指定 a CompositeKey或表示模型没有主键。复合主键在这里更详细地讨论:复合主键。

要指示模型不应该有主键,然后设置.primary_key = False

例子:

class BlogToTag(Model):
    """A simple "through" table for many-to-many relationship."""
    blog = ForeignKeyField(Blog)
    tag = ForeignKeyField(Tag)

    class Meta:
        primary_key = CompositeKey('blog', 'tag')

class NoPrimaryKey(Model):
    data = IntegerField()

    class Meta:
        primary_key = False

7.3.2 表名

默认情况下,Peewee 会根据你的模型类的名称自动生成一个表名。生成表名的方式取决于 的值 Meta.legacy_table_names。默认情况下,legacy_table_names=True以避免破坏向后兼容性。但是,如果您希望使用新的和改进的表名生成,您可以指定legacy_table_names=False.

此表显示了模型名称如何转换为 SQL 表名称的差异,具体取决于 的值legacy_table_names:

Model namelegacy_table_names=Truelegacy_table_names=False(新)
Useruseruser
UserProfileuserprofileuser_profile
APIResponseapiresponseapi_response
WebHTTPRequestwebhttprequestweb_http_request
mixedCamelCasemixedcamelcasemixed_camel_case
Name2Numbers3XYZname2numbers3xyzname2_numbers3_xyz

注意力

为了保持向后兼容性,当前版本(Peewee 3.x)legacy_table_names=True默认指定。

在下一个主要版本(Peewee 4.0)中,legacy_table_names默认值为False.

要显式指定模型类的表名,请使用table_name Meta 选项。此功能可用于处理可能使用了尴尬命名约定的预先存在的数据库模式:

class UserProfile(Model):
    class Meta:
        table_name = 'user_profile_tbl'

如果您希望实现自己的命名约定,可以指定 table_functionMeta 选项。此函数将与您的模型类一起调用,并应将所需的表名作为字符串返回。假设我们公司规定表名应该小写并以“_tbl”结尾,我们可以将其实现为表函数:

def make_table_name(model_class):
    model_name = model_class.__name__
    return model_name.lower() + '_tbl'

class BaseModel(Model):
    class Meta:
        table_function = make_table_name

class User(BaseModel):
    # table_name will be "user_tbl".

class UserProfile(BaseModel):
    # table_name will be "userprofile_tbl".

7.4 索引和约束

Peewee 可以在单个或多个列上创建索引,可选地包括一个 UNIQUE约束。Peewee 还支持模型和字段上的用户定义约束。

7.4.1 单列索引和约束

单列索引是使用字段初始化参数定义的。以下示例在用户名字段上添加唯一索引,在电子邮件字段上添加普通索引:

class User(Model):
    username = CharField(unique=True)
    email = CharField(index=True)

要在列上添加用户定义的约束,您可以使用 constraints参数将其传入。您可能希望指定一个默认值作为架构的一部分,或者添加一个CHECK约束,例如:

class Product(Model):
    name = CharField(unique=True)
    price = DecimalField(constraints=[Check('price < 10000')])
    created = DateTimeField(
        constraints=[SQL("DEFAULT (datetime('now'))")])

7.4.2 多列索引

多列索引可以使用嵌套元组定义为元属性。每个数据库索引都是一个 2 元组,其中的第一部分是字段名称的元组,第二部分是一个布尔值,指示索引是否应该是唯一的。

class Transaction(Model):
    from_acct = CharField()
    to_acct = CharField()
    amount = DecimalField()
    date = DateTimeField()

    class Meta:
        indexes = (
            # create a unique on from/to/date
            (('from_acct', 'to_acct', 'date'), True),

            # create a non-unique on from/to
            (('from_acct', 'to_acct'), False),
        )

笔记

如果您的索引元组仅包含一项,请记住添加尾随逗号:

class Meta:
    indexes = (
        (('first_name', 'last_name'), True),  # Note the trailing comma!
    )

7.4.3 高级索引创建

Peewee 支持更结构化的 API,用于使用Model.add_index()方法或直接使用 ModelIndex帮助器类在模型上声明索引。

例子:

class Article(Model):
    name = TextField()
    timestamp = TimestampField()
    status = IntegerField()
    flags = IntegerField()

# Add an index on "name" and "timestamp" columns.
Article.add_index(Article.name, Article.timestamp)

# Add a partial index on name and timestamp where status = 1.
Article.add_index(Article.name, Article.timestamp,
                  where=(Article.status == 1))

# Create a unique index on timestamp desc, status & 4.
idx = Article.index(
    Article.timestamp.desc(),
    Article.flags.bin_and(4),
    unique=True)
Article.add_index(idx)

警告

SQLite 不支持参数化查询。这意味着当使用 SQLite 创建涉及表达式或标量值的索引时,您将需要使用 帮助器声明索引:CREATE
INDEXSQL

# SQLite does not support parameterized CREATE INDEX queries, so
# we declare it manually.
Article.add_index(SQL('CREATE INDEX ...'))

详情请参阅add_index()。

有关更多信息,请参阅:

  • Model.add_index()
  • Model.index()
  • ModelIndex
  • Index

7.4.4 表约束

Peewee 允许您向您的 中添加任意约束Model,这将在创建模式时成为表定义的一部分。

例如,假设您有一个people表,其中包含两列的复合主键,即人员的名字和姓氏。您希望另一个表与people表相关,为此,您需要定义一个外键约束:

class Person(Model):
    first = CharField()
    last = CharField()

    class Meta:
        primary_key = CompositeKey('first', 'last')

class Pet(Model):
    owner_first = CharField()
    owner_last = CharField()
    pet_name = CharField()

    class Meta:
        constraints = [SQL('FOREIGN KEY(owner_first, owner_last) '
                           'REFERENCES person(first, last)')]

您还可以CHECK在表级别实现约束:

class Product(Model):
    name = CharField(unique=True)
    price = DecimalField()

    class Meta:
        constraints = [Check('price < 10000')]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

岳涛@心馨电脑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值