一、安装Tortoise ORM
pip install tortoise-orm
(注:Fastapi TortoiseORM 与 Django ORM写法非常相似)
二、常用字段参数
- pk: 是否为主键字段,默认
False
。 - unique: 是否唯一,默认
False
。 - index: 是否为索引字段,默认
False
。 - null: 是否允许为 NULL,默认
False
。 - default: 字段的默认值,可以是函数或静态值。
- description: 字段的描述,通常用于文档化。
- max_length: 最大长度,主要用于
CharField
。 - precision: 精度,主要用于
DecimalField
。 - scale: 小数位数,主要用于
DecimalField
。 - generated: 是否是数据库生成的字段(如自动递增字段)。
- read_only: 是否为只读字段。
- constraints: 定义复杂的约束条件。
三、 常用字段类型及参数
基本字段类型
字段类型 | 参数(选项) | 说明 |
|
, | 字符串字段,需定义最大长度 |
|
| 长文本字段 |
|
, , | 整数字段 |
| 同上 | 大整数字段 |
|
, | 浮点字段 |
|
, | 高精度浮点字段 |
|
| 布尔字段 |
|
, | 日期时间字段,支持自动更新 |
|
, | 日期字段 |
关系字段
字段类型 | 参数(选项) | 说明 |
|
, , | 外键字段 |
|
, , | 一对一关系字段 |
|
, , | 多对多关系字段 |
四、模型案例
from tortoise.models import Model
from tortoise import fields
class User(Model):
id = fields.IntField(pk=True)
username = fields.CharField(max_length=50, unique=True)
email = fields.CharField(max_length=100, unique=True, null=True)
password = fields.CharField(max_length=128)
is_active = fields.BooleanField(default=True)
created_at = fields.DatetimeField(auto_now_add=True)
updated_at = fields.DatetimeField(auto_now=True)
class Meta:
table = "user"
indexes = [("username", "email")] # 联合索引
五、表单验证器
Pydantic 用于数据验证 ,可以结合 Tortoise-ORM 一起使用
from pydantic import BaseModel, EmailStr, Field
# 创建 Pydantic 模型用于表单验证
class UserCreate(BaseModel):
username: str = Field(..., max_length=50)
email: EmailStr
password: str = Field(..., min_length=6)
class UserResponse(BaseModel):
id: int
username: str
email: EmailStr
is_active: bool
created_at: str
class Config:
orm_mode = True
六、Pydantic 模型与 Tortoise 模型结合
创建用户的 API 示例
from fastapi import FastAPI, HTTPException
from models import User # Tortoise 模型
from schemas import UserCreate, UserResponse # Pydantic 模型
app = FastAPI()
@app.post("/users/", response_model=UserResponse)
async def create_user(user: UserCreate):
existing_user = await User.filter(username=user.username).first()
if existing_user:
raise HTTPException(status_code=400, detail="Username already exists")
new_user = await User.create(**user.dict())
return new_user
七、关系表
1、一对一关系
一对一关系表示两个模型之间存在唯一的对应关系。例如,一个人只有一个身份证,一个身份证只属于一个人。
from tortoise import fields, models
class IDCard(models.Model):
id = fields.IntField(pk=True)
number = fields.CharField(max_length=20, unique=True)
person: fields.OneToOneRelation["Person"]
class Meta:
table = "id_card"
class Person(models.Model):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=50)
id_card: fields.OneToOneRelation[IDCard] = fields.OneToOneField(
"models.IDCard", related_name="person", on_delete=fields.OnDelete.CASCADE
)
class Meta:
table = "person"
fields.OneToOneField
用于定义一对一关系。related_name
参数用于在关联的模型中反向访问。on_delete
参数定义了当关联的模型被删除时的行为,例如fields.OnDelete.CASCADE
表示级联删除。
async def create_person_with_id_card():
id_card = await IDCard.create(number="1234567890")
person = await Person.create(name="张三", id_card=id_card)
print(f"创建了人员:{person.name},身份证号:{person.id_card.number}")
async def get_person_by_id_card_number(number: str):
id_card = await IDCard.get(number=number)
person = await id_card.person
print(f"通过身份证号 {number} 找到了人员:{person.name}")
2、一对多关系
一对多关系表示一个模型可以关联多个其他模型。例如,一个作者可以有多篇文章,一篇文章只能有一个作者。
from tortoise import fields, models
class Author(models.Model):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=50)
articles: fields.ReverseRelation["Article"]
class Meta:
table = "author"
class Article(models.Model):
id = fields.IntField(pk=True)
title = fields.CharField(max_length=100)
content = fields.TextField()
author: fields.ForeignKeyRelation[Author] = fields.ForeignKeyField(
"models.Author", related_name="articles", on_delete=fields.OnDelete.CASCADE
)
class Meta:
table = "article"
fields.ForeignKeyField
用于定义外键,表示多的一方。
fields.ReverseRelation
用于在一的一方反向访问多的一方。
async def create_author_with_articles():
author = await Author.create(name="李四")
await Article.create(title="文章1", content="内容1", author=author)
await Article.create(title="文章2", content="内容2", author=author)
print(f"作者 {author.name} 发表了 {await author.articles.all().count()} 篇文章")
async def get_articles_by_author_name(name: str):
author = await Author.get(name=name)
articles = await author.articles.all()
for article in articles:
print(f"文章标题:{article.title}")
3、多对多关系
多对多关系表示两个模型之间可以互相关联多个。例如,一个学生可以选择多门课程,一门课程可以被多个学生选择。
from tortoise import fields, models
class Student(models.Model):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=50)
courses: fields.ManyToManyRelation["Course"] = fields.ManyToManyField(
"models.Course", related_name="students"
)
class Meta:
table = "student"
class Course(models.Model):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=50)
students: fields.ManyToManyRelation[Student]
class Meta:
table = "course"
fields.ManyToManyField
用于定义多对多关系。Tortoise ORM 会自动创建一个中间表来维护这种关系。
async def create_student_with_courses():
student = await Student.create(name="王五")
course1 = await Course.create(name="语文")
course2 = await Course.create(name="数学")
await student.courses.add(course1, course2)
print(f"学生 {student.name} 选择了 {await student.courses.all().count()} 门课程")
async def get_students_by_course_name(name: str):
course = await Course.get(name=name)
students = await course.students.all()
for student in students:
print(f"选修该课程的学生:{student.name}")