文章目錄
- Fastapi ORM操作
- 1、創建模型
- 2、創建數據庫連接配置文件
- 3、啟動項目
- 4、根據模型類創建數據庫表
- 1. 初始化配置,只需要使用一次
- 2. 初始化數據庫,一般情況下只用一次
- 3. 更新模型并進行遷移
- 4. 重新執行遷移,寫入數據庫
- 5. 回到上一個版本
- 6. 查看歷史遷移記錄
- 5、選課系統接口開發
- (1)all查詢,查詢出來的是個list類型數據
- (2)過濾查詢,查詢指定內容filter,得到的依然是list類型數據
- (3)get方法,直接查詢
- (4)模糊查詢,查詢學號大于2001的學生
- (5)values查詢
- (6)將數據庫數據顯示到web頁面
Fastapi ORM操作
在大型的web開發中,我們肯定會用到數據庫操作,那么FastAPI也支持數據庫的開發,你可以用 PostgreSQL、MySQL、 SQLite Oracle 等。本文用SQLite為例。我們看下在fastapi是如何操作設計數據庫的。
ORM是“對象-關系-映射”的簡稱。(Object Relational Mapping,簡稱ORM)
fastapi是一個很優秀的框架,但是缺少一個合適的orm,官方代碼里面使用的是sqlalchemy,Tortoise ORM 是受 Django 啟發的易于使用的異步 ORM (對象關系映射器)。
Tortoise ORM 目前支持以下[數據庫]
- PostgreSQL >= 9.4(使用asyncpg)
- SQLite(使用aiosqlite)
- MySQL/MariaDB
安裝tortoise
pip install tortoise
安裝數據模型遷移工具
pip install aerich
我用的mysql,因此還需要安裝aiomysql包:
pip install aiomysql
aerich的功能類似于django的migrate。
1、創建模型
以選課系統為例:
創建個模型類文件 models.py
#導入tortoisefrom tortoise.models import Model
from tortoise import fields#創建班級類
class Clas(Model):name = fields.CharField(max_length=255, description='班級名稱')#創建老師類
class Teacher(Model):id = fields.IntField(pk=True)name = fields.CharField(max_length=255, description='姓名')tno = fields.IntField(description='賬號')pwd = fields.CharField(max_length=255, description='密碼')#課程表
class Course(Model):id = fields.IntField(pk=True)name = fields.CharField(max_length=255, description='課程名')teacher = fields.ForeignKeyField('models.Teacher', related_name='courses', description='課程講師')#創建學生類
class Student(Model):id = fields.IntField(pk=True)sno = fields.IntField(description='學號')#description 在接口文檔有個顯示pwd = fields.CharField(max_length=255, description='密碼')name = fields.CharField(max_length=255, description='姓名')# 一對多,反向查詢時使用related_nameclas = fields.ForeignKeyField('models.Clas', related_name='students')# 多對多courses = fields.ManyToManyField('models.Course', related_name='students',description='學生選課表')
2、創建數據庫連接配置文件
創建settings.py 配置文件
TORTOISE_ORM = {'connections': {'default': {# 'engine': 'tortoise.backends.asyncpg', PostgreSQL'engine': 'tortoise.backends.mysql', # MySQL or Mariadb'credentials': {'host': '10.10.0.52','port': '3306','user': 'root','password': 'Jingxxxxxxxx','database': 'fastapi','minsize': 1,'maxsize': 5,'charset': 'utf8mb4',"echo": True}},},'apps': {'models': {#這個models就是自己配置的models.py位置'models': ['models'],'default_connection': 'default',}},'use_tz': False,'timezone': 'Asia/Shanghai'
}
3、啟動項目
main.py 啟動項目
from fastapi import FastAPI # FastAPI 是一個為你的 API 提供了所有功能的 Python 類。
import uvicorn
from tortoise.contrib.fastapi import register_tortoisefrom settings import TORTOISE_ORM#創建應用程序,app是應用程序名
app = FastAPI() # 這個實例將是創建你所有 API 的主要交互對象。這個 app 同樣在如下命令中被 uvicorn 所引用# 該方法會在fastapi啟動時觸發,內部通過傳遞進去的app對象,監聽服務啟動和終止事件
# 當檢測到啟動事件時,會初始化Tortoise對象,如果generate_schemas為True則還會進行數據庫遷移
# 當檢測到終止事件時,會關閉連接
register_tortoise(app,#數據庫配置信息config=TORTOISE_ORM,# generate_schemas=True, # 如果數據庫為空,則自動生成對應表單,生產環境不要開# add_exception_handlers=True, # 生產環境不要開,會泄露調試信息
)if __name__ == '__main__':#注意,run的第一個參數 必須是文件名:應用程序名uvicorn.run("quickstart:app", port=8080, reload=True, workers=1)
啟動沒報錯表示正常連接到了數據庫
4、根據模型類創建數據庫表
aerich是一種ORM遷移工具,需要結合tortoise異步orm框架使用。安裝aerich
1. 初始化配置,只需要使用一次
初始化之前,需要在settings.py中將aerich自帶的models也配置上
在中高端執行命令
aerich init -t settings.TORTOISE_ORM # TORTOISE_ORM配置的位置)
初始化完會在當前目錄生成一個文件:pyproject.toml和一個文件夾:migrations
- pyproject.toml:保存配置文件路徑,低版本可能是aerich.ini
- migrations:存放遷移文件
2. 初始化數據庫,一般情況下只用一次
將我們在models.py里面配置的表創建到數據庫中
aerich init-db
- 此時數據庫中就有相應的表格
- 如果
TORTOISE_ORM
配置文件中的models
改了名,則執行這條命令時需要增加--app
參數,來指定你修改的名字
查看數據庫,數據庫中就有了我們在模型類里面配置的表
看下migrations里面的py文件,就是創建表語句
3. 更新模型并進行遷移
我們在創建模型類之后,通常也會修改
修改model類,重新生成遷移文件,比如添加一個字段
我們給course類添加個地址字段
aerich migrate [–name] (標記修改操作) # aerich migrate --name add_column --name是給這次遷移起個名字
不加–name,有個默認的名字
遷移文件名的格式為 {version_num}{datetime}{name|update}.py。
注意,此時sql并沒有執行,數據庫中course表中沒有xxx字段
4. 重新執行遷移,寫入數據庫
aerich upgrade
此時,就把模型類中新添加愛的字段更新到數據庫中了
5. 回到上一個版本
aerich downgrade
再看下數據庫,新加的字段又沒了,回退了
6. 查看歷史遷移記錄
aerich history
5、選課系統接口開發
先看看各個表數據
班級表
教師表
課程表
學生表
學生課程表
我們在項目下建個包api,在這個包里面寫接口
api/student.py
from fastapi.exceptions import HTTPException#導入models
from models import *from pydantic import BaseModel
from typing import List, Union
from fastapi import APIRouterapi_student = APIRouter()#查看所有學生,注意,tortoise處理數據庫要用異步,路徑函數前面加async
@api_student.get("/")
async def getAllStudent():#注意,與數據庫的操作要加await,得到的是列表類型數據,[Student(),Student(),Student()....]students = await Student.all()print('students',students,type(students))return students#查看某個學生,基于路徑參數
@api_student.get("/{student_id}")
async def getOneStudent(student_id:int):#注意,與數據庫的操作要加awaitstudent = await Student.all().values("name", "clas__name")return student
在main.py導入api,并做路由分發
from fastapi import FastAPI # FastAPI 是一個為你的 API 提供了所有功能的 Python 類。
import uvicorn
from tortoise.contrib.fastapi import register_tortoisefrom settings import TORTOISE_ORM#導入api
from api.student import api_student#創建應用程序,app是應用程序名
app = FastAPI() # 這個實例將是創建你所有 API 的主要交互對象。這個 app 同樣在如下命令中被 uvicorn 所引用#路由分發
app.include_router(api_student, prefix="/student", tags=["學生信息接口", ])# 該方法會在fastapi啟動時觸發,內部通過傳遞進去的app對象,監聽服務啟動和終止事件
# 當檢測到啟動事件時,會初始化Tortoise對象,如果generate_schemas為True則還會進行數據庫遷移
# 當檢測到終止事件時,會關閉連接
register_tortoise(app,#數據庫配置信息config=TORTOISE_ORM,# generate_schemas=True, # 如果數據庫為空,則自動生成對應表單,生產環境不要開# add_exception_handlers=True, # 生產環境不要開,會泄露調試信息
)if __name__ == '__main__':#注意,run的第一個參數 必須是文件名:應用程序名uvicorn.run("main:app", port=8080, reload=True, workers=1)
運行程序
執行查詢所有學生
(1)all查詢,查詢出來的是個list類型數據
循環遍歷
#循環打印
for stu in students:
print(stu.name, stu.sno)
(2)過濾查詢,查詢指定內容filter,得到的依然是list類型數據
student = await Student.filter(name='liuxin')
print(student,type(student))
#得到具體數據
print(student[0].name)
(3)get方法,直接查詢
#get方法
student = await Student.get(name="wangfang")
print(student,type(student))
print(student.name,student.sno)
此時得到的就是模型類對象,可以直接獲取屬性值
(4)模糊查詢,查詢學號大于2001的學生
students = await Student.filter(sno__gt=2001)
print(students)
得到的也是列表
#查詢學號是2001和2002的學生,在某個范圍內,用__in
students = await Student.filter(sno__in=[2001,2002])
(5)values查詢
只查出指定字段數據,得到的是列表套字典數據,有幾個字典,取決于查詢出幾條記錄
students = await Student.filter(sno__range=[1, 10000]).values(‘name’,‘sno’)
for stu in students:
print(stu)
(6)將數據庫數據顯示到web頁面
在student.py 這個api文件里面
返回頁面模板
#導入模板的包
from fastapi.templating import Jinja2Templates# 實例化Jinja2對象,并將文件夾路徑設置為以templates命名的文件夾
templates = Jinja2Templates(directory="templates")接口:
@api_student.get("/index")
async def show_student(request:Request):students = await Student.all()return templates.TemplateResponse('index.html', #第一個參數放模板文件{'request': request, # 注意,返回模板響應時,必須有request鍵值對,且值為Request請求對象'students':students}, #context上下文對象,是個字典)
創建templates文件夾下的index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>學生信息</title>
</head>
<body><p>學生信息頁面</p><ul>{% for stu in students %}<li>姓名: {{stu.name}} 學號: {{stu.sno}}</li>{% endfor%}
</ul></body>
</html>
啟動程序,訪問
瀏覽器訪問
當然,也可以借助bootstrap讓頁面更好看
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>學生信息</title><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
</head>
<body><div class="col-md-8 offset-md-2"><h2>學生信息</h2><table class="table table-hover table-striped"><thead><tr><td>姓名</td><td>學號</td><td>班級</td></tr></thead><tbody>{% for student in students%}<tr><td>{{student.name}}</td><td>{{student.sno}}</td><td>{{student.clas_id}}</td></tr>{%endfor%}</tbody>
</table>
</div></body>
</html>