在 Python 中实现数据库分页一般是通过 SQL 查询中的 LIMIT
和 OFFSET
子句来实现的。以下是一个示例,展示如何在 ORM 设计中添加分页功能。
分页实现思路
- 确定每页记录数:用户可以指定每页显示的记录数量。
- 计算偏移量 :根据当前页码和每页记录数计算
OFFSET
值。 - 更新查询逻辑 :在查询方法中添加
LIMIT
和OFFSET
。
修改后的 ORM 代码
在先前的 ORM 示例中,我们将 BaseModel
添加分页功能:
python
import sqlite3
from abc import ABC, abstractmethod
class 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
@abstractmethod
def table_name(cls):
pass
@classmethod
def create_table(cls, db: Database):
"""创建表"""
raise NotImplementedError("Subclasses must implement this method.")
@classmethod
def all(cls, db: Database):
"""获取所有记录"""
db.cursor.execute(f"SELECT * FROM {cls.table_name()}")
return db.cursor.fetchall()
@classmethod
def 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()
@classmethod
def delete(cls, db: Database, record_id):
"""删除记录"""
db.cursor.execute(f"DELETE FROM {cls.table_name()} WHERE id = ?", (record_id,))
db.commit()
@classmethod
def paginate(cls, db: Database, page: int, per_page: int):
"""分页查询"""
offset = (page - 1) * per_page
db.cursor.execute(f"SELECT * FROM {cls.table_name()} LIMIT ? OFFSET ?", (per_page, offset))
return db.cursor.fetchall()
class User(BaseModel):
"""用户模型"""
@classmethod
def table_name(cls):
return "users"
@classmethod
def 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 语法。