七、模型和字段
Model类、Field实例和模型实例都映射到数据库概念:
事物 | 对应… |
---|---|
Model class | Database table |
Field instance | Column on a table |
Model instance | Row in a database table |
以下代码显示了定义数据库连接和模型类的典型方式。 |
import datetime
from peewee import *
db = SqliteDatabase('my_app.db')
class BaseModel(Model):
class Meta:
database = db
class User(BaseModel):
username = CharField(unique=True)
class Tweet(BaseModel):
user = ForeignKeyField(User, backref='tweets')
message = TextField()
created_date = DateTimeField(default=datetime.datetime.now)
is_published = BooleanField(default=True)
- 创建一个Database.
db = SqliteDatabase('my_app.db')
该db对象将用于管理与 Sqlite 数据库的连接。在此示例中,我们使用的是SqliteDatabase,但您也可以使用其他数据库引擎之一。
- 创建一个指定我们的数据库的基本模型类。
class BaseModel(Model):
class Meta:
database = db
定义一个建立数据库连接的基本模型类是一种很好的做法。这使您的代码干燥,因为您不必为后续模型指定数据库。
模型配置保存在一个名为Meta. 这个约定是从 Django 借来的。元 配置传递给子类,所以我们项目的模型都将继承 BaseModel。您可以使用 Model.Meta 配置许多不同的属性。
- 定义一个模型类。
class User(BaseModel):
username = CharField(unique=True)
模型定义使用在 SQLAlchemy 或 Django 等其他流行的 ORM 中看到的声明式样式。请注意,我们正在扩展BaseModel类,因此User模型将继承数据库连接。
我们已经明确定义了一个带有唯一约束的用户名列。因为我们没有指定主键,peewee 会自动添加一个名为 id的自增整数主键字段。
笔记
如果您想在现有数据库中开始使用 peewee,您可以使用pwiz,一个模型生成器来自动生成模型定义。
7.1 字段
该类Field用于描述 Model属性到数据库列的映射。每种字段类型都有对应的SQL存储类(即varchar、int),python数据类型与底层存储之间的转换是透明处理的。
创建Model类时,字段被定义为类属性。这对于 django 框架的用户来说应该很熟悉。这是一个例子:
class User(Model):
username = CharField()
join_date = DateTimeField()
about_me = TextField()
在上面的示例中,由于没有使用 初始化任何字段,因此 primary_key=True将自动创建一个自动递增的主键并命名为“id”。Peewee 用于AutoField表示一个自动递增的整数主键,这意味着primary_key=True.
有一种特殊类型的字段 ,ForeignKeyField它允许您以直观的方式表示模型之间的外键关系:
class Message(Model):
user = ForeignKeyField(User, backref='messages')
body = TextField()
send_date = DateTimeField(default=datetime.datetime.now)
这允许您编写如下代码:
>>> print(some_message.user.username)
Some User
>>> for message in some_user.messages:
... print(message.body)
some message
another message
yet another message
笔记
有关模型之间的外键、连接和关系的深入讨论,请参阅关系和连接文档。
有关字段的完整文档,请参阅字段 API 说明
7.1.1 字段类型表
字段类型 | Sqlite | PostgreSQL | MySQL |
---|---|---|---|
AutoField | integer | serial | integer |
BigAutoField | integer | bigserial | bigint |
IntegerField | integer | integer | integer |
BigIntegerField | integer | bigint | bigint |
SmallIntegerField | integer | smallint | smallint |
IdentityField | not supported | int identity | not supported |
FloatField | real | real | real |
DoubleField | real | double precision | double precision |
DecimalField | decimal | numeric | numeric |
CharField | varchar | varchar | varchar |
FixedCharField | char | char | char |
TextField | text | text | text |
BlobField | blob | bytea | blob |
BitField | integer | bigint | bigint |
BigBitField | blob | bytea | blob |
UUIDField | text | uuid | varchar(40) |
BinaryUUIDField | blob | bytea | varbinary(16) |
DateTimeField | datetime | timestamp | datetime |
DateField | date | date | date |
TimeField | time | time | time |
TimestampField | integer | integer | integer |
IPField | integer | bigint | bigint |
BooleanField | integer | boolean | bool |
BareField | untyped | not supported | not supported |
ForeignKeyField | integer | integer | integer |
笔记
在上表中没有看到您要查找的字段?创建自定义字段类型并将它们与您的模型一起使用很容易。
- 创建自定义字段
- Database,特别是fields参数。
7.1.2 字段初始化参数
所有字段类型接受的参数及其默认值:
null = False
– 允许空值index = False
– 在该列上创建索引unique = False
– 在此列上创建唯一索引。另请参阅添加复合索引。column_name = None
– 显式指定数据库中的列名。default = None
- 任何值或可调用用作未初始化模型的默认值primary_key = False
– 表的主键constraints = None
- 一个或多个约束,例如[Check(‘price > 0’)]sequence = None
– 序列名称(如果后端支持)collation = None
– 用于排序字段/索引的排序规则unindexed = False
- 指示虚拟表上的字段应该是无索引的(仅限 SQLite)choices = None
– 包含 2 个元组的可选迭代value,displayhelp_text = None
– 表示该字段的任何有用文本的字符串verbose_name = None
– 表示该字段的“用户友好”名称的字符串index_type = None
– 指定自定义索引类型,例如,对于 Postgres,您可以指定 a’BRIN’或’GIN’索引。
7.1.3 有些字段采用特殊参数……
字段类型 | 特殊参数 |
---|---|
CharField | max_length |
FixedCharField | max_length |
DateTimeField | formats |
DateField | formats |
TimeField | formats |
TimestampField | resolution,utc |
DecimalField | max_digits, decimal_places, auto_round, rounding |
ForeignKeyField | model, field, backref, on_delete, on_update, deferrable lazy_load |
BareField | adapt |
笔记
两者default和choices都可以在数据库级别分别实现为DEFAULT和CHECK
CONSTRAINT,但是任何应用程序更改都需要模式更改。因此,default纯粹在 python
中实现,choices未经验证,仅用于元数据目的。要添加数据库(服务器端)约束,请使用constraints 参数。
7.1.3 默认字段值
Peewee 可以在创建对象时为字段提供默认值。例如,要将IntegerField默认值设为 0 而不是NULL,您可以使用默认值声明该字段:
class Message(Model):
context = TextField()
read_count = IntegerField(default=0)
在某些情况下,默认值是动态的可能是有意义的。一个常见的场景是使用当前日期和时间。Peewee 允许您在这些情况下指定一个函数,该函数的返回值将在创建对象时使用。注意我们只提供函数,我们实际上并没有调用 它:
class Message(Model):
context = TextField()
timestamp = DateTimeField(default=datetime.datetime.now)
笔记
如果您使用的字段接受可变类型(list、dict等),并希望提供默认值,则最好将默认值包装在一个简单的函数中,这样多个模型实例就不会共享一个引用相同的底层对象:
def house_defaults():
return {‘beds’: 0, ‘baths’: 0}class House(Model):
number = TextField()
street = TextField()
attributes = JSONField(default=house_defaults)
数据库还可以为字段提供默认值。虽然 peewee 没有明确提供用于设置服务器端默认值的 API,但您可以使用该constraints参数来指定服务器默认值:
class Message(Model):
context = TextField()
timestamp = DateTimeField(constraints=[SQL('DEFAULT CURRENT_TIMESTAMP')])
笔记
请记住:使用default参数时,值由 Peewee 设置,而不是实际表和列定义的一部分。