作者归档:Fidum

32 ORM之多对多添加记录

多对多关系,会有一张新的表进行存储,这里我们接上回,添加学生的时候,需要把学生选的课程一并添加到数据库中。

@students.post('/students')
async def add_students(student_in: StudentIn):
    # 插入数据

    # 方式二
    student = await Student.create(name=student_in.name,pwd=student_in.pwd,student_number=student_in.student_number,classes_id=student_in.classes_id)

    # 添加多对多记录
    courses = await Courses.filter(id__in=student_in.courses)
    print("courses", courses)
    await student.courses.add(*courses)
    print("student", student.courses)

    return student

courses = await Courses.filter(id__in=student_in.courses)
这句就是在课程表中过滤学生选的课程id

await student.courses.add(*courses)
这句就是将学生选的课,一行一行插入到多对多关系表中

比如,我添加一个学生kuxie,除了基本信息外,他还选了id是6和7的课程(在courses表中可以查看)。
在文档中测试:
file
点击execute后,查看各表:
student表:
file
courses表:
file
多对多关系表:
file
学生和选的课程关系存储成功。

31 ORM 添加表记录

FastAPI tortoise ORM添加数据,在此接口方法下实现:
方式一:

@students.post('/students')
async def add_students(stu: Student):
    return {"msg": "添加学生"}

传入json,并且做校验

class StudentIn(BaseModel):
    # id : int  # 可以不传
    name: str
    pwd: str
    student_number: int
    # 在数据库中,这个字段就变成了classes_id
    classes_id: int
    courses: List[int] = []

    @field_validator('name')
    @classmethod
    def name_must_not_be_empty(cls, v):
        if not v:
            raise ValueError('Name cannot be empty')
        return v

@students.post('/students')
async def add_students(student_in: StudentIn):
    # 插入数据
    # 方式一
    # 先实例化
    student = Student(name=student_in.name,pwd=student_in.pwd,student_number=student_in.student_number,classes_id=student_in.classes_id)
    # 这里的classes_id就是一对多的传参了
    # 然后存入数据库
    await student.save()

    return "添加了一个学生"

id我们之前设置过,是自增的:

mysql> desc student;
+----------------+-------------+------+-----+---------+----------------+
| Field          | Type        | Null | Key | Default | Extra          |
+----------------+-------------+------+-----+---------+----------------+
| id             | int         | NO   | PRI | NULL    | auto_increment |
| name           | varchar(32) | NO   |     | NULL    |                |
| pwd            | varchar(32) | NO   |     | NULL    |                |
| student_number | int         | NO   |     | NULL    |                |
| classes_id     | int         | NO   | MUL | NULL    |                |
+----------------+-------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

方式二:

@students.post('/students')
async def add_students(student_in: StudentIn):
    # 方式二
    student = await Student.create(name=student_in.name,pwd=student_in.pwd,student_number=student_in.student_number,classes_id=student_in.classes_id)

    return student

以上代码的测试,都可以通过FastAPI自带的接口文档进行测试。

30 ORM响应页面数据

前后端分离的场景下,用户访问的是前端服务器,后端开发的接口是给前端用的,这个要谨记。

了解一下前后端不分离的模式

@student.get("/index.html")
async def getAllStudent():
    students = await Student.all()
    return students

这里直接返回的话,返回的是json的数据,可以在接口文档中看的很清楚。

前后端不分离的话,我们需要将数据嵌入前端中,然后返回给用户。

# 需要导入jinja2
from fastapi.templating import Jinja2Templates
from fastapi import Request

@students.get('/students')
async def get_all_students(request: Request):  # 这里必须携带Request的实例
    all_students = await Student.all()
    templates = Jinja2Templates(directory=r".\chapter3\学习ORM\apis\templates")

    return templates.TemplateResponse(
        "index.html",{            # 模板文件写这里
        "request": request,
        "students": all_students  #传递的参数写这里
        }
    )

模板文件需要在合适的位置编辑好,数据插入的位置,类似这样

<html>
  <body>
    <ul>
      {% for student in students %}
          <li>姓名:{{ student.name }}, 学号:{{ student.student_number }}</li>
      {% endfor %}
    </ul>
  </body>
</html>

再尝试访问,就可以看到返回的渲染后的页面了
file
然后 老师讲了一下bootstrap的一些用法,看看就好。

29 选课系统之ORM查询操作

tortoise ORM具体操作

29 选课系统之ORM查询操作

学生选课为例

先手动在class表中添加几条记录,用insert也好、用pycharm的数据库插件也好、用navicat也好

id 班级
13 计算机1班
14 计算机2班
15 软件1班

teacher表也添加几条记录

id name pwd tno
11 xhs 123 1
22 dhs 456 2

course表也添加几条记录

id name teacher_id
6 python开发 11
7 操作系统原理 22

student也添加

id name pwd sno class
1 tom tom666 202501 13
2 jerry jerry666 202502 14
3 tafei tafei666 202503 14

student_course表添加

student_id course_id
2 6
2 7
3 7
  • 查询所有学生

在students_api.py文件中编辑,先导入我们定义的模型:

from mymodels import *

然后在查询所有学生的函数(可能是get_all_students)下面,进行tortoise ROM的查询操作:

students = Student.all()
# 查询所有记录,students是queryset的数据类型,可以遍历,
# 一张表相当于一个类,一条记录相当于一个对象的实例化
# 遍历的时候需要注意,不可以直接 for student in students: pass
# 这里需要变成异步任务,不然会报错
函数名前加上async,Student.all()前面加上await
async def get_all_students():
    students = await Student.all()
    ... ...

过滤查询filter,返回的还是QuerySet,就算其中只有一个元素,也得按照元素位置取值或者遍历

# students = await Student.filter(name="tom")
students = await Student.filter(class_id=13)

过滤查询get,返回模型类对象,不用遍历

student = await Student.get(class_id=13)
# 可以直接使用对象的方法调用属性
print(student.name)

模糊查询

  • 字段+两个下划线+查询符号
    students = await Student.filter(sno__gt=202502)          # sno__gt这里表示大于的意思
    students = await Student.filter(sno__in=[202502,202503]) # 筛选其中的两个
    students = await Student.filter(sno__range=[202501,202503])  # 范围查询

value查询

students = await Student.all().values("name")
students = await Student.filter(sno__gt=202502).values("name","sno")
# 这里就相当于只返回name字段的结果,相当于select name from xxx;
# 返回结果是字典组成的列表,返回多少条记录,该列表中就有多少个字典,
# 字典的格式和你查询的字段相对应,比如[{'name': 'xhs'}, {'name': 'dhs'}]或者
# [{'name': 'xhs', 'sno': 2}, {'name': 'dhs', 'sno': 3}]

今日书籍推荐(精神、激素相关)

  1. 《为什么斑马不得胃溃疡》(罗伯特·萨波尔斯基)

豆瓣8.8分,斯坦福神经生物学教授经典之作

重点:用动物比喻解释压力(皮质醇)如何摧毁身体,含肾上腺疲劳的现代人应对方案

适合人群:想理解压力与疾病关联的入门读者

  1. 《大脑里的快递员》(丹尼尔·亚蒙)

神经科学家写的神经递质科普

亮点:多巴胺/血清素章节用快递配送比喻解释机制,附自测量表

特别章节:第5章「肾上腺:你的压力开关」

  1. 《身体从未忘记》(贝塞尔·范德科尔克)

创伤与激素关系的普利策奖入围作品

实用价值:提供重置HPA轴(下丘脑-垂体-肾上腺轴)的具体方法

6月16日4:09记

这一次,我没有回家,却有望重获新生。

之前,北漂久了,人麻木了,回趟家是个很好的选择,回到家乡,看看儿时玩过的小溪、水库、充满回忆的学校,沐浴着家乡的阳光,呼吸着田埂间清新的气息,不用刻意做什么,能量瞬间充满全身,我感恩,我的童年是相对幸福的。起码,比现在幸福吧。

刚看完一集老高和小茉的视频,大概是讲如何消除烦恼,里面提到了一个小办法,就是有烦恼就写下来,我差点忘记了这个这个方法,本来之前用过的,人脑烦心事的处理总是混乱的,但写下来,你再用眼睛直观的去看,可能就清晰了。

我真的烦透了世俗中人的各种试探,甚至让我反胃,低略的手段让我感觉俗不可耐,有时间吧,试探我的人还是我平时认为关系还不错的,这样我就为难了,因为我不知道我是该精心编个故事骗骗你呢,还是风轻云淡的随意敷衍一下。什么?你想要我内心的正确答案?我靠,你真是不仅智商低下还爱做白日梦。

扯远了啊,说重获新生呢,谁家孩子有这样重获新生的。不行,有点困了~