在 Python 中实现数据库分页一般是通过 SQL 查询中的 LIMIT
和 OFFSET
子句来实现的。以下是一个示例,展示如何在 ORM 设计中添加分页功能。
分页实现思路
- 确定每页记录数:用户可以指定每页显示的记录数量。
- 计算偏移量:根据当前页码和每页记录数计算
OFFSET
值。 - 更新查询逻辑:在查询方法中添加
LIMIT
和OFFSET
。
修改后的 ORM 代码
在先前的 ORM 示例中,我们将 BaseModel
添加分页功能:
python">import sqlite3
from abc import ABC, abstractmethodclass Database:"""数据库连接管理类"""def __init__(self, db_name):self.connection = sqlite3.connect(db_name)self.cursor = self.connection.cursor()def commit(self):self.connection.commit()def close(self):self.connection.close()class BaseModel(ABC):"""模型基类"""@classmethod@abstractmethoddef table_name(cls):pass@classmethoddef create_table(cls, db: Database):"""创建表"""raise NotImplementedError("Subclasses must implement this method.")@classmethoddef all(cls, db: Database):"""获取所有记录"""db.cursor.execute(f"SELECT * FROM {cls.table_name()}")return db.cursor.fetchall()@classmethoddef insert(cls, db: Database, **kwargs):"""插入记录"""columns = ', '.join(kwargs.keys())placeholders = ', '.join(['?'] * len(kwargs))sql = f"INSERT INTO {cls.table_name()} ({columns}) VALUES ({placeholders})"db.cursor.execute(sql, tuple(kwargs.values()))db.commit()@classmethoddef delete(cls, db: Database, record_id):"""删除记录"""db.cursor.execute(f"DELETE FROM {cls.table_name()} WHERE id = ?", (record_id,))db.commit()@classmethoddef paginate(cls, db: Database, page: int, per_page: int):"""分页查询"""offset = (page - 1) * per_pagedb.cursor.execute(f"SELECT * FROM {cls.table_name()} LIMIT ? OFFSET ?", (per_page, offset))return db.cursor.fetchall()class User(BaseModel):"""用户模型"""@classmethoddef table_name(cls):return "users"@classmethoddef create_table(cls, db: Database):db.cursor.execute("""CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT NOT NULL,age INTEGER)""")db.commit()# 使用示例if __name__ == "__main__":db = Database("example.db")# 创建表User.create_table(db)# 插入数据User.insert(db, name="Alice", age=30)User.insert(db, name="Bob", age=25)User.insert(db, name="Charlie", age=35)User.insert(db, name="David", age=40)User.insert(db, name="Eve", age=28)# 分页查询page_number = 1 # 当前页码records_per_page = 2 # 每页记录数users_page_1 = User.paginate(db, page=page_number, per_page=records_per_page)print(f"第 {page_number} 页用户列表:", users_page_1)page_number = 2 # 查询下一页users_page_2 = User.paginate(db, page=page_number, per_page=records_per_page)print(f"第 {page_number} 页用户列表:", users_page_2)# 清理db.close()
代码说明
-
paginate方法:
- 接受
page
和per_page
参数。 - 计算
OFFSET
的值。 - 执行带有
LIMIT
和OFFSET
的 SQL 查询以实现分页。
- 接受
-
使用示例:
- 在插入多个用户后,调用
paginate
方法获取特定页的数据。
- 在插入多个用户后,调用
注意事项
- 上述分页实现仅支持基本的分页功能,如需进一步实现更复杂的分页逻辑(如总页数、总记录数等),可以扩展该方法。
- 进行分页查询时,应考虑索引的使用以提高性能,因为
OFFSET
随着页面数量的增加可能会导致性能下降。 - 在使用其他类型的数据库时(如 MySQL 和 PostgreSQL),
LIMIT
和OFFSET
的用法是相似的,但在某些情况下可能需要调整 SQL 语法。