7、fastapi的orm模式

pip install tortoise-orm==0.25.0 aerich==0.9.0 aiomysql==0.2.0 tomlkit==0.13.2

Aerich 初始化

在项目根目录运行以下命令:

aerich init -t settings.TORTOISE_ORM

这将生成:

  • pyproject.toml:Aerich 配置文件,指定迁移配置。
  • migrations/:迁移文件目录,存放生成的 .sql 文件。
aerich init-db

生成和应用迁移

  1. 生成迁移文件: 当模型发生变更时,运行以下命令生成迁移文件:

    aerich migrate --name "info"
    
  2. 应用迁移: 运行以下命令将迁移应用到数据库:

    aerich upgrade
    
  3. 验证迁移: 检查迁移历史

    aerich history
    
  4. 回滚迁移:回退到指定版本

    aerich downgrade
    

1、main.py文件

from fastapi import FastAPI, Request
import uvicorn
from tortoise.contrib.fastapi import register_tortoise
from settings import TORTOISE_ORM
from api.student import student_api

app = FastAPI()
app.include_router(student_api, prefix="/student", tags=["选课系统的学生接口"])

# fastapi一旦运行,register_tortoise已经执行,实现监控
# aerich init -t settings.TORTOISE_ORM
register_tortoise(
    app=app,
    config=TORTOISE_ORM
)

if __name__ == '__main__':
    uvicorn.run("main:app", port=8010, reload=True)


2、student.py文件

from typing import List

from fastapi import APIRouter
from pydantic import BaseModel, field_validator
from fastapi.exceptions import HTTPException

from orm.models import *

student_api = APIRouter()


@student_api.get("/")
async def get_student():
    # 1、查询所有
    # students = await Student.all()
    # print("students", students)
    # for student in students:
    #     print(student.name, student.sno)

    # 2、过滤查询
    # students = await Student.filter(name="rain")
    # students = await Student.filter(clas_id=2)
    # print("students", students)
    # stu = await Student.get(id=1)
    # print(stu.name, stu.sno)

    # 3、模糊查询
    # stus = await Student.filter(sno__gt=2001)
    # stus = await Student.filter(sno__range=[1, 10000])
    # stus = await Student.filter(sno__in=[2001, 2002])
    # print(stus)

    # 4、values查询
    # stus = await Student.all().values("name", "sno")
    # print(stus)

    # 5、一对一查询
    avlin = await Student.get(name="avlin")
    print(await avlin.clas.values("name"))
    students__ = await Student.all().values("name", "sno", "clas__name")

    # 多对多查询
    students_ = await avlin.courses.all().values("name", "teacher__name")
    print(students_)
    students = await Student.all().values("name", "sno", "courses__name", "courses__teacher__name")
    print(students)

    return students


class StudentIn(BaseModel):
    name: str
    pw: str
    sno: int
    clas_id: int
    courses: List[int] = []

    @field_validator("name")
    def name_must_alpha(cls, value):
        assert value.isalpha(), "Name must be alpha"
        return value

    @field_validator("sno")
    def sno_must_be_valid(cls, value):
        assert 1000 < value < 10000, "学号要在1000-10000的范围内"
        return value


@student_api.post("/")
async def add_student(student_in: StudentIn):
    # 1、方式1
    # student = Student(name=student_in.name, pw=student_in.pw, sno=student_in.sno, clas_id=student_in.clas_id)
    # await student.save()

    # 2、方式2
    student = await Student.create(name=student_in.name, pw=student_in.pw, sno=student_in.sno, clas_id=student_in.clas_id)

    # 多对多关系
    choose_courses = await Course.filter(id__in=student_in.courses)
    await student.courses.add(*choose_courses)


    return student


@student_api.get("/{student_id}")
def get_one_student(student_id: int):
    return {"操作": f"查看id={student_id}的学生"}


@student_api.put("/{student_id}")
async def update_one_student(student_id: int, student_in: StudentIn):
    data = student_in.model_dump()
    courses = data.pop("courses")

    await Student.filter(id=student_id).update(**data)

    # 设置多对多的选修课
    edit_stu = await Student.get(id=student_id)
    await edit_stu.courses.clear()
    choose_courses = await Course.filter(id__in=courses)
    await edit_stu.courses.add(*choose_courses)


    return edit_stu


@student_api.delete("/{student_id}")
async def delete_one_student(student_id: int):
    delete_count = await Student.filter(id=student_id).delete()
    if delete_count == 0:
        raise HTTPException(status_code=404, detail="没有找到该学生")
    return {"操作": f"删除了id={student_id}的学生"}


3、models.py文件

from tortoise.models import Model
from tortoise import fields

# 排列的顺序不能错了


class Clas(Model):
    id = fields.IntField(pk=True)
    name = fields.CharField(max_length=32, description="班级名称")


class Teacher(Model):
    id = fields.IntField(pk=True)
    name = fields.CharField(max_length=32, description="姓名")
    pwd = fields.CharField(max_length=32, description="密码")
    tno = fields.IntField(description="老师编号")


class Course(Model):
    id = fields.IntField(pk=True)
    name = fields.CharField(max_length=32, description="课程名字")
    teacher = fields.ForeignKeyField("models.Teacher", related_name="courses")


class Student(Model):
    id = fields.IntField(pk=True)
    name = fields.CharField(max_length=32, description="学生姓名")
    pw = fields.CharField(max_length=32, description="学生密码")
    sno = fields.IntField(description="学生学号")

    # 一对多的关系
    clas = fields.ForeignKeyField("models.Clas", related_name="students")

    # 多对多的关系
    courses = fields.ManyToManyField("models.Course", related_name="students")

4、settings.py文件

TORTOISE_ORM = {
    'connections': {
        'default': {
            # 'engine': 'tortoise.backends.asyncpg', PostgreSQL
            'engine': 'tortoise.backends.mysql',  # MySQL or Mariadb
            'credentials': {
                'host': '127.0.0.1',
                'port': 3306,
                'user': 'root',
                'password': 'wwb18770648678',
                'database': 'fastapi',
                'minsize': 1,
                'maxsize': 5,
                'charset': 'utf8mb4',
            },
        },
    },
    'apps': {
        'models': {
            'models': ['orm.models', 'aerich.models'],
            'default_connection': 'default',

        }
    },
    'use_tz': False,
    'timezone': 'Asia/Shanghai'
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值