Tortoise-ORM 提供了丰富且直观的字段类型(Field Types),用于定义数据库模型(Model)。这些字段类型不仅映射到数据库列,还支持索引、默认值、唯一约束、外键关系等。


📌 一、核心字段类型速查表

字段类型用途对应数据库类型典型参数
IntField整数(主键常用)INTEGER / BIGINTpk=True, default=0
CharField短字符串VARCHAR(n)max_length=50, unique=Trueindex=True
TextField长文本TEXTnull=True 允许为空
BooleanField布尔值BOOLEANdefault=False
DatetimeField日期时间DATETIME / TIMESTAMPauto_now_add, auto_now
DateField日期DATE
UUIDField唯一标识UUID/CHAR(36)
BinaryField二进制数据BLOB不支持过滤和更新操作
FloatField浮点数REAL / DOUBLEgt=0值大于0
DecimalField精确小数(金融)DECIMAL(p,s)max_digits=10, decimal_places=2
JSONFieldJSON 数据JSON / TEXTencoder(自定义编码器)、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允许数据库为 NULLemail = 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=Truedefault=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)

✅ 五、最佳实践建议

  1. 主键统一用 IntField(pk=True)(除非需要 UUID)
  2. 字符串必设 max_length(避免 TEXT 性能问题)
  3. 金额用 DecimalField,不用 FloatField
  4. 时间字段用 auto_now_add / auto_now 管理
  5. 外键记得设 related_name,方便反向查询
  6. 频繁查询的字段加 index=True
  7. 敏感字段(如密码)不要返回给前端(用 Pydantic 过滤)