课程管理平台后端开发
需求
开发一个具有课程管理模块的后端系统,模块功能包含增删改查。
使用 MySQL + SQLAlchemy + Flask 完成整个后端流程,实现课程管理功能。
实现思路
接口设计
接口名称 | 接口入参 | 接口返回 | 请求 url | 请求方法 |
---|---|---|---|---|
课程新增 | 课程相关信息 | 创建成功 | /course | post |
课程删除 | 课程 id | 删除成功 | /course | delete |
课程修改 | 课程相关信息 | 修改成功 | /course | put |
获取课程 | 课程 id | 课程相关信息 | /course | get |
获取课程列表 | 课程列表相关信息 | /course/list | get |
开发
安装相关依赖
pip install SQLAlchemy
pip install pymysql
pip install pydantic
pip install flask
声明 SQLAlchemy 的 ORM 模型
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import declarative_base
# 声明基类
Base = declarative_base()
# 定义表结构
class Course(Base):
__tablename__ = "t_course"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(30))
detail = Column(String(255), default="")
为了更为规范地定义和使用数据接口,可以使用 pydantic 库。pydantic 库是一种常用的用于数据接口 schema 定义与检查的库,通过这种方式,数据的传递将会更为安全。
Pydantic 在运行时强制执行类型提示,并在数据无效时提供用户友好的错误信息。
from typing import Optional
from pydantic import BaseModel, ConfigDict, constr
# 定义 pydantic 对象,用于数据验证与解析
class CourseModel(BaseModel):
# 允许通过其他类实例来生成并初始化一个 Pydantic 实例
model_config = ConfigDict(from_attributes=True)
# id 属性为整型
id: int
# name 属性为字符串,最大长度为 30
name: constr(max_length=30)
# Optional 的作用是可选类型,告诉 IDE 或者框架这个参数除了给定的默认值外还可以是 None
detail: Optional[constr(max_length=255)] = ""
使用 pydantic 对象进行数据验证与解析,更多的实现可以参考 pydantic 官方文档。
创建数据库
进入 mysql
执行以下命令创建数据库 course。
CREATE DATABASE course;
配置 MySQL 创建数据库表
在当前文件添加 python 代码并执行,注意替换正确的连接信息。
# 连接 mysql
# mysql 登录用户名
username = "root"
# mysql 登录密码
pwd = "hogwarts"
# mysql 域名
host = "127.0.0.1"
# mysql 端口
port = 3306
# 要操作的数据库名
database = "course"
engine = create_engine(f"mysql+pymysql://{username}:{pwd}@{host}:{port}/{database}")
if __name__ == '__main__':
# 创建表
Base.metadata.create_all(engine)
进入数据库,查看表是否成功创建。
use course;
show tables;
可以看到 t_course 表已经成功创建了。
定义 app 和创建 session 对象
# 定义 app
app = Flask(__name__)
# 创建会话
DBSession = sessionmaker(bind=engine)
# 获取会话实例
db_session: Session = DBSession()
编写课程管理增删改查接口
# 使用蓝图管理路由
course_manager = Blueprint("course", __name__, url_prefix="/course")
# 新增课程接口
# 蓝图对象可以直接调用对应请求方法,等价于 methods=["POST"]
@course_manager.post("")
def create_course():
course_json = request.get_json()
print(f"请求体为 {course_json}")
# 验证传输过来的请求体是否正确
try:
# 使用 pydantic 把请求参数转为 pydantic 对象
CourseModel.model_validate(course_json)
# 如果没有错误则表示请求参数符合要求
except ValidationError as e:
# 如果有错误,则捕捉对应错误
print(e)
return {
"errcode": 10002,
# 通过 e.errors() 获取错误列表
# repr 为内置函数,返回一个对象的 string 格式
"errmsg": repr(e.errors())
}
# 通过课程名称和详情进行创建
db_session.add(Course(**course_json))
# 提交操作
db_session.commit()
# 关闭连接
db_session.close()
return {
"errcode": 0,
"errmsg": "创建课程成功!"
}
# 获取课程
@course_manager.get(f"/<int:course_id>")
def get_course(course_id: int):
print(f"要获取的课程 id 为 {course_id}")
# 通过课程 id 在数据库中查询
course_data = db_session.query(Course).filter_by(id=course_id).first()
# 如果查询结果为空
if course_data is None:
return {
"errcode": 10001,
"errmsg": "课程不存在"
}
# 通过 pydantic 把查询结果对象转为字典格式
datas = CourseModel.model_validate(course_data).model_dump()
print(datas, type(datas))
# 关闭连接
db_session.close()
return {
"errcode": 0,
"errmsg": f"获取 id 为 {course_id} 的课程信息成功!",
"datas": datas
}
# 获取全部课程列表
@course_manager.get("/list")
def get_courses():
# 查询数据库获取全部课程列表
course_datas = db_session.query(Course).all()
print(f"获取到的课程列表为 {course_datas}")
# 使用列表推导式获取全部数据列表,列表中元素为每个查询结果的字典格式
datas = [CourseModel.model_validate(course).model_dump() for course in course_datas]
# 关闭连接
db_session.close()
return {
"errcode": 0,
"errmsg": "获取全部课程列表成功!",
"datas": datas
}
# 修改课程
@course_manager.put("")
def update_course():
# 获取 json 格式请求体
course_json = request.get_json()
print(f"请求体为 {course_json}")
# 验证传输过来的请求体是否正确
try:
# 使用 pydantic 把请求参数转为 pydantic 对象
CourseModel.model_validate(course_json)
except ValidationError as e:
print(e)
return {
"errcode": 10002,
"errmsg": repr(e.errors())
}
# 构造课程对象
course_data = Course(**course_json)
# 根据课程 id 进行查询,如果查找不到结果则返回课程不存在
if db_session.query(Course).filter_by(id=course_data.id).first() is None:
return {
"errcode": 10001,
"errmsg": "课程不存在"
}
# 使用 pydantic 把请求数据转为字典
data = CourseModel.model_validate(course_json).model_dump()
print(data ,type(data))
# 更新数据
db_session.query(Course).filter_by(id=course_data.id).update(data)
# 提交操作
db_session.commit()
# 关闭连接
db_session.close()
return {
"errcode": 0,
"errmsg": "课程修改成功"
}
# 删除课程
@course_manager.delete(f"/<int:course_id>")
def delete_course(course_id: int):
print(f"要删除的课程 id 为 {course_id}")
# 根据id进行查询
course_data = db_session.query(Course).filter(Course.id == course_id).first()
# 如果查询结果为空,则返回课程不存在
if course_data is None:
return {
"errcode": 10001,
"errmsg": "课程不存在"
}
# 删除查找到的课程
db_session.delete(course_data)
# 提交操作
db_session.commit()
# 关闭连接
db_session.close()
return {
"errcode": 0,
"errmsg": "课程删除成功"
}
运行程序
if __name__ == '__main__':
app.register_blueprint(course_manager)
app.run(debug=True, port=5055)
测试接口
可以通过 postman 或者 requests 进行接口测试,查看接口功能是否正常实现。
相关接口
总结
- 环境准备
- 需求分析
- 接口设计
- 接口实现
- 声明 SQLAlchemy 的 ORM 模型
- 创建数据库
- 定义 app 创建 session 对象
- 编写课程管理增删改查接口
相关文档地址
- SQLAlchemy:https://docs.sqlalchemy.org/en/20/
- Flask:https://flask.palletsprojects.com/en/2.3.x/
- pydantic:https://docs.pydantic.dev/2.0/usage/models/