详见我的提问“自定义分页组件类无法正常实例化”。
为了方便做浏览器的分页组件自定义了一个 CustomPaginator 类,paginator.py代码如下:
class CustomPaginator:
def __init__(self, queryset, page_number, items_per_page=10, visible_page_count=7):
"""
初始化分页器
:param queryset: 数据查询集
:param page_number: 当前页码
:param items_per_page: 每页显示的条目数
:param visible_page_count: 分页导航中可见的页码数量
"""
self.queryset = queryset
self.total_items = self.queryset.count() # 查询的数据(对象)个数
self.page_number = self._validate_page_number(page_number)
self.items_per_page = items_per_page
self.visible_page_count = visible_page_count
self.total_pages = self._calculate_total_pages() # 分页个数
def _validate_page_number(self, page_number):
"""
校验并调整页码
:param page_number: 用户输入的页码
:return: 合法的页码,(不超过最大页码,不小于1)
"""
return max(1, min(page_number, self._calculate_total_pages()))
def _calculate_total_pages(self):
"""计算总页数,确保向上取整"""
return (self.total_items + self.items_per_page - 1) // self.items_per_page
def get_page_data(self):
"""获取当前页的数据"""
start_index = (self.page_number - 1) * self.items_per_page
end_index = self.page_number * self.items_per_page
return self.queryset[start_index:end_index]
def get_pagination_html(self, base_url='?'):
"""
生成分页 HTML
:param base_url: 基础 URL,用于生成带参数的链接
"""
half_range = self.visible_page_count // 2
pagination_links = [f'<li><a href="{base_url}page=1">首页</a></li>'] # 首页
if self.page_number > 1:
pagination_links.append(f'<li><a href="{base_url}page={self.page_number - 1}" '
f'aria-label="Previous"><span aria-hidden="true">«</span></a></li>') # 上一页
for i in range(1, self.total_pages + 1):
if i == self.page_number:
pagination_links.append(f'<li class="active"><a href="{base_url}page={i}">{i}</a></li>') # 当前页
elif abs(i - self.page_number) <= half_range:
pagination_links.append(f'<li><a href="{base_url}page={i}">{i}</a></li>')
if self.page_number < self.total_pages:
pagination_links.append(f'<li><a href="{base_url}page={self.page_number + 1}" '
f'aria-label="Next"><span aria-hidden="true">»</span></a></li>') # 下一页
pagination_links.append(f'<li><a href="{base_url}page={self.total_pages}">尾页</a></li>') # 尾页
实例化对象后,访问相关网页,浏览器报错提示没有 'items_per_page' 属性:
问题是我明明已经在初始化方法中确认了默认值 items_per_page=10 ,为什么还报错没有 'items_per_page' 属性?怪了。
问Chat GPT折腾了半天,问不出个所以然,问豆包倒是弄清楚了,调用内置方法的时候需要的属性未定义,一个简单的顺序问题。
豆包的回答如下:
在你提供的代码中,报错'CustomPaginator' object has no attribute 'items_per_page'
看起来很奇怪,因为你确实在__init__
方法里定义了items_per_page
。经过仔细查看,问题出在_validate_page_number
方法里:
def _validate_page_number(self, page_number):
"""
校验并调整页码
:param page_number: 用户输入的页码
:return: 合法的页码
"""
# 这里调用了 self._calculate_total_pages(),而此时 self.total_items 没问题,但 self.items_per_page 还未赋值
return max(1, min(page_number, self._calculate_total_pages()))
在_validate_page_number
函数中,你调用了self._calculate_total_pages()
,而这个函数依赖于self.items_per_page
。但在__init__
函数执行流程里,_validate_page_number
是在self.items_per_page
被赋值之前调用的,所以导致了这个属性在那一刻看起来没有被定义。
你可以把self.page_number = self._validate_page_number(page_number)
这一行代码移到self.items_per_page = items_per_page
之后,修改后的__init__
方法如下:
def __init__ (self, queryset, page_number, items_per_page=10,
visible_page_count=7):
"""
初始化分页器
:param queryset: 数据查询集
:param page_number: 当前页码
:param items_per_page: 每页显示的条目数
:param visible_page_count: 分页导航中可见的页码数量
"""
self.queryset = queryset
self.total_items = self.queryset.count() # 查询的数据(对象)个数
self.items_per_page = items_per_page
self.page_number = self._validate_page_number(page_number)
self.visible_page_count = visible_page_count
self.total_pages = self._calculate_total_pages() # 分页个数
这样就能保证items_per_page
已经被正确赋值,再调用_validate_page_number
就不会出错了。
我还特意看了看Chat GPT的聊天记录,发现在第二次出现异常时,Chat GPT给出了正确的代码顺序,但是没有提出原因,看来国内的AI也挺牛的。