Tortoise-ORM 提供了丰富且直观的字段类型(Field Types),用于定义数据库模型(Model)。这些字段类型不仅映射到数据库列,还支持索引、默认值、唯一约束、外键关系等。
📌 一、核心字段类型速查表
| 字段类型 | 用途 | 对应数据库类型 | 典型参数 |
|---|---|---|---|
IntField | 整数(主键常用) | INTEGER / BIGINT | pk=True, default=0 |
CharField | 短字符串 | VARCHAR(n) | max_length=50, unique=True,index=True |
TextField | 长文本 | TEXT | null=True 允许为空 |
BooleanField | 布尔值 | BOOLEAN | default=False |
DatetimeField | 日期时间 | DATETIME / TIMESTAMP | auto_now_add, auto_now |
DateField | 日期 | DATE | — |
UUIDField | 唯一标识 | UUID/CHAR(36) | — |
BinaryField | 二进制数据 | BLOB | 不支持过滤和更新操作 |
FloatField | 浮点数 | REAL / DOUBLE | gt=0值大于0 |
DecimalField | 精确小数(金融) | DECIMAL(p,s) | max_digits=10, decimal_places=2 |
JSONField | JSON 数据 | JSON / TEXT | encoder(自定义编码器)、decoder(自定义解码器) |
ForeignKeyField | 外键关联 | INTEGER(引用主键) | related_name, on_delete |
✅ 二、详细字段说明与示例
1️⃣ IntField —— 整数字段
from tortoise.models import Model
from tortoise import fields
class User(Model):
id = fields.IntField(pk=True) # 主键
age = fields.IntField(default=18, description="用户年龄")- ✅
pk=True表示主键(自动自增) - ✅ 可用于普通整数字段(如计数器)
2️⃣ CharField —— 固定长度字符串
class User(Model):
username = fields.CharField(max_length=32, unique=True)
email = fields.CharField(max_length=255, index=True) # 加索引加速查询- ⚠️ 必须指定
max_length - ✅
unique=True→ 唯一约束 - ✅
index=True→ 创建数据库索引
3️⃣ TextField —— 长文本(无长度限制)
class Post(Model):
title = fields.CharField(max_length=200)
content = fields.TextField() # 博客正文、评论等- ✅ 适合存储文章、日志、描述等长内容
- ❌ 不支持
max_length
4️⃣ BooleanField —— 布尔值
class User(Model):
is_active = fields.BooleanField(default=True)
is_superuser = fields.BooleanField(default=False)- ✅ 默认值很常用(避免
NULL)
5️⃣ DatetimeField —— 日期时间(带时区)
class Post(Model):
created_at = fields.DatetimeField(auto_now_add=True) # 创建时自动设为当前时间
updated_at = fields.DatetimeField(auto_now=True) # 每次 save() 自动更新- ✅
auto_now_add:仅首次创建时设置 - ✅
auto_now:每次保存都更新(类似“最后修改时间”)
💡 存储的是 UTC 时间,建议应用层处理时区。
6️⃣ DateField —— 仅日期(不含时间)
class Event(Model):
event_date = fields.DateField() # 如生日、会议日期7️⃣ FloatField vs DecimalField
FloatField(近似值,不推荐用于金额)
class Product(Model):
rating = fields.FloatField() # 4.5 星DecimalField(精确值,金融/金额必用)
class Order(Model):
amount = fields.DecimalField(max_digits=10, decimal_places=2)
# 表示最多 8 位整数 + 2 位小数,如 12345678.99- ✅
max_digits:总位数 - ✅
decimal_places:小数位数
⚠️ 永远不要用 FloatField 存钱!8️⃣ JSONField —— 存储 JSON 对象
class Config(Model):
settings = fields.JSONField(default=dict) # 存储用户配置- ✅ 支持 dict/list 等 Python 对象
- ✅ 数据库需支持 JSON(PostgreSQL、MySQL 5.7+、SQLite 3.38+)
- ❌ SQLite 旧版本会 fallback 到 TEXT(自动序列化)
9️⃣ ForeignKeyField —— 外键关联(一对多)
class User(Model):
name = fields.CharField(max_length=50)
class Post(Model):
title = fields.CharField(max_length=100)
author = fields.ForeignKeyField('models.User', related_name='posts')查询示例:
# 获取用户的所有文章
user = await User.get(id=1)
posts = await user.posts.all() # ← 通过 related_name 反向查询
# 获取文章的作者
post = await Post.get(id=1).prefetch_related('author')
print(post.author.name)- ✅
'models.User':模型路径(模块名.类名) - ✅
related_name:反向关系名称(在 User 上生成.posts属性) - ✅ 默认
on_delete=RESTRICT(可设为CASCADE,SET_NULL等)
🔟 OneToOneField —— 一对一(如用户资料)
class User(Model):
name = fields.CharField(max_length=50)
class Profile(Model):
bio = fields.TextField()
user = fields.OneToOneField('models.User', on_delete=fields.CASCADE)🔟 ManyToManyField —— 多对多(如标签)
class Tag(Model):
name = fields.CharField(max_length=30, unique=True)
class Post(Model):
title = fields.CharField(max_length=100)
tags = fields.ManyToManyField('models.Tag', related_name='posts')使用:
post = await Post.create(title="Hello")
tag = await Tag.create(name="python")
await post.tags.add(tag) # 关联
# 查询带标签的文章
posts = await Post.filter(tags__name="python").all()🛠 三、通用字段参数(适用于大多数字段)
| 参数 | 说明 | 示例 |
|---|---|---|
null | 允许数据库为 NULL | email = CharField(null=True) |
default | 默认值(Python 值或 callable) | created = DatetimeField(default=datetime.utcnow) |
description | 字段注释(生成文档用) | age = IntField(description="年龄") |
index | 创建数据库索引 | username = CharField(max_length=32, index=True) |
unique | 唯一约束 | email = CharField(max_length=255, unique=True) |
💡 注意:
null=True≠default=None- 如果字段允许为空,通常设
null=True+default=None
📂 四、完整模型示例(用户 + 文章 + 标签)
from tortoise.models import Model
from tortoise import fields
from datetime import datetime
class User(Model):
id = fields.IntField(pk=True)
username = fields.CharField(max_length=32, unique=True, index=True)
email = fields.CharField(max_length=255, unique=True)
is_active = fields.BooleanField(default=True)
created_at = fields.DatetimeField(auto_now_add=True)
class Tag(Model):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=30, unique=True)
class Post(Model):
id = fields.IntField(pk=True)
title = fields.CharField(max_length=200)
content = fields.TextField()
author = fields.ForeignKeyField('models.User', related_name='posts')
tags = fields.ManyToManyField('models.Tag', related_name='posts')
published = fields.BooleanField(default=False)
created_at = fields.DatetimeField(auto_now_add=True)
views = fields.IntField(default=0)✅ 五、最佳实践建议
- 主键统一用
IntField(pk=True)(除非需要 UUID) - 字符串必设
max_length(避免 TEXT 性能问题) - 金额用
DecimalField,不用FloatField - 时间字段用
auto_now_add/auto_now管理 - 外键记得设
related_name,方便反向查询 - 频繁查询的字段加
index=True - 敏感字段(如密码)不要返回给前端(用 Pydantic 过滤)
评论已关闭