慕慕手记项目日记2025.3.3
慕慕手记项目日记2025.3.3
现在需要对慕慕手记进行数据库表的补充设计和创建评论表和orm框架封装,重点学会如何理解orm框架是如何工作的。
慕慕手记项目数据库表的补充设计
现在需要设计评论表:
CREATE TABLE `comment` (
`id` int unsigned COMMENT '评论id' NOT NULL AUTO_INCREMENT,
`user_id` int unsigned COMMENT '用户id' NOT NULL,
`article_id` int unsigned COMMENT '文章id' NOT NULL,
`ipaddr` varchar(255) COMMENT 'ip地址' COLLATE utf8mb4_general_ci NOT NULL,
`reply_id` int unsigned COMMENT '回复id' DEFAULT 0,
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4;
-
核心字段
id
自增主键,无符号整型(避免负数),用于唯一标识评论,保证数据检索效率。user_id
&article_id
无符号整型,分别关联用户表和文章表,说明评论必须由已注册用户对某篇文章发出(无匿名评论)。ipaddr
存储用户IP地址(兼容IPv6需45字符,此处预留255),用于风险控制(如识别恶意刷评)、地域分析或审计需求。
-
评论层级关系
-
reply_id
默认值为0表示顶层评论(直接评论文章),非0时指向父评论的
id
,实现
嵌套评论
功能。例如:
sql复制代码-- 查询某文章下所有顶层评论 SELECT * FROM comment WHERE article_id = 123 AND reply_id = 0; -- 查询某条评论的所有回复 SELECT * FROM comment WHERE reply_id = 456;
这种设计适合
两级回复
(评论+子评论),若需多级嵌套(如微博式树状回复),需结合闭包表或路径枚举优化。
-
-
时间管理
create_time
自动记录评论提交时间,用于排序(如“最新评论优先”)或时间范围统计。update_time
仅在评论修改时更新(如用户编辑内容),若评论不允许修改可省略此字段。
ORM
什么是ORM?ORM(Object-Relational Mapping) 是一种编程技术,用于在面向对象编程语言和关系型数据库之间建立桥梁。简单来说,它把数据库中的表、字段、记录映射成程序中的类、属性、对象,让开发者可以用面向对象的方式操作数据库,而无需直接编写复杂的 SQL 语句。
数据库连接的基本封装
在这里我们重点实现一下数据库连接的基本封装,因为ORM也是使用这种方式进行封装然后再供开发者使用。
import pymysql
class MyROM:
def __init__(self):
# 初始化数据库连接
# 使用pymysql.connect方法创建一个到指定MySQL数据库的连接
# 参数包括:host(主机地址), port(端口号), user(用户名), password(密码), database(数据库名), charset(字符集)
conn = pymysql.connect(host='172.27.13.88', port=3306, user='root', password='123456', database='mumushouji',
charset='utf8mb4')
# 创建游标对象,用于执行SQL语句和获取结果
cursor = conn.cursor()
# 将游标对象保存为类的一个属性,以便其他方法使用
self.cursor = cursor
def query_all_user(self):
# 定义查询所有用户的SQL语句
sql = """
select * from USER
"""
# 执行SQL查询
self.cursor.execute(sql)
# 获取所有查询结果
result = self.cursor.fetchall()
# 返回查询结果
return result
if __name__ == '__main__':
# 确保这段代码仅在作为脚本直接运行时被执行,而不是在被导入为模块时执行
# 创建MyROM类的实例
myrom = MyROM()
# 调用query_all_user方法查询所有用户信息
result = myrom.query_all_user()
# 打印查询结果
print(result)
面向过程实现ORM框架封装
import pymysql
class MyROM:
def __init__(self):
conn = pymysql.connect(host='172.27.13.88', port=3306, user='root', password='123456', database='mumushouji',
charset='utf8mb4'
)
cursor = conn.cursor()
self.cursor = cursor
def execute(self, sql):
self.cursor.execute(sql)
result = self.cursor.fetchall()
return result
class User:
table_name = 'USER'
def query_all(self):
sql = "select * from " + self.table_name
return MyROM().execute(sql)
def query_one(self):
sql = "select * from %s limit 1 " % (self.table_name)
return MyROM().execute(sql)
class Acticle:
table_name = 'acticle'
def query_all(self):
sql = "select * from " + self.table_name
return MyROM().execute(sql)
def query_one(self):
sql = "select * from %s limit 1 " % (self.table_name)
return MyROM().execute(sql)
class comment:
table_name = 'comment'
def query_all(self):
sql = "select * from " + self.table_name
return MyROM().execute(sql)
def query_one(self):
sql = "select * from %s limit 1 " % (self.table_name)
return MyROM().execute(sql)
if __name__ == '__main__':
user = User()
acticle = Acticle()
comment = comment()
r1 = comment.query_one()
r2 = user.query_one()
print(r2)
面向对象优雅实现ORM框架封装
# SELECT字段处理
if select_params is not None and isinstance(select_params, list):
sql = "SELECT " + ", ".join(select_params) + f" FROM {self.table_name}"
else:
sql = "SELECT * FROM " + self.table_name
# WHERE条件处理
where_values = []
if where_params:
where_clauses = []
for k, v in where_params.items():
where_clauses.append(f"{k} = '{v}'") # 保留直接拼接但修复引号问题
sql += " WHERE " + " AND ".join(where_clauses)
# 统一添加LIMIT(根据需求调整)
if not where_params or len(where_params) > 0:
sql += " LIMIT 1"
print("[Final SQL]", sql) # 调试输出
return MyROM().execute(sql)
ORM框架实现插入语句封装
def insert(self):
keys = []
values = []
print(self.__dict__)
for k, v in self.__dict__.items():
keys.append(k)
values.append(v)
sql = "insert into %s(%s) values ('%s')" % (self.table_name, ','.join(keys), "','".join(values))
print(sql)
return MyROM().execute(sql)