django視圖之分頁
在網站開發時,肯定會遇到分頁的事情需要處理,在django中也是如此,在Django中處理分頁一般會使用到兩個類django.core.paginator.Paginator和django.core.paginator.Page,要想在Django中做分頁處理,首先我們就需要了解一下這兩個類。
首先在使用Django的通用視圖時,在get_context_data方法中返回的內容中就包含當前頁的分類信息,get_context_data方法的返回值中封裝了當前頁的分頁信息,即Paginator和Page類的對象。其中Paginator被封裝成的對象對應的鍵為‘paginator‘,Page被封裝成的對象對應的鍵為‘page_obj‘
Paginator類對象常用屬性和方法,主要是整個列表相關信息:
count:總共有多少條數據。
num_pages:總共有多少頁。
page_range:頁面的區間。比如有三頁,那麽就range(1,4)。
Page類對象常用屬性和方法,主要是當前頁相關信息:
has_next():是否還有下一頁。
has_previous():是否還有上一頁。
next_page_number():下一頁的頁碼。
previous_page_number():上一頁的頁碼。
number:當前頁碼。
start_index():當前這一頁的第一條數據的索引值。
end_index():當前這一頁的最後一條數據的索引值。
普通分頁:在手動寫分頁的時候,我們只需要使用到原生的Paginator和Page類對象,而這些對象直接被封裝在get_context_data的返回值之中,我們直接使用就可以了,借助於bootstrap的分頁相關樣式,在模板中的代碼如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文章列表</title>
{# 引入bootstrap樣式 #}
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<ul>
{# 列表內容 #}
{% for article in article_list %}
<li>
{{ article.title }}
</li>
{% endfor %}
<ul class="pagination">
{# 分頁內容 #}
{# 上一頁 #}
{% if page_obj.has_previous %}
<li><a href="{% url ‘front:article_list‘ %}?page={{ page_obj.previous_page_number }}">上一頁</a></li>
{% else %}
<li class="disabled"><a href="javascript:void(0);">上一頁</a></li>
{% endif %}
{# 中間頁 #}
{% for num_page in paginator.page_range %}
{% if page_obj.number == num_page %}
<li class="active"><a href="{% url ‘front:article_list‘ %}?page={{ num_page }}">{{ num_page }}</a></li>
{% else %}
<li><a href="{% url ‘front:article_list‘ %}?page={{ num_page }}">{{ num_page }}</a></li>
{% endif %}
{% endfor %}
{# 下一頁 #}
{% if page_obj.has_next %}
<li><a href="{% url ‘front:article_list‘ %}?page={{ page_obj.next_page_number }}">下一頁</a></li>
{% else %}
<li class="disabled"><a href="javascript:void(0);">下一頁</a></li>
{% endif %}
</ul>
</ul>
</body>
</html>
上面的分頁寫法,如果頁數過於多,那麽將會很難看,而且也不是很實用,所以上面的分頁寫法只適合於很少的頁數的分頁,不是通用的寫法,下面我們就來編寫一種通用的分頁寫法
通用分頁算法:通用分頁算法需要我們對原始的Paginator和Page對象進行進一步的封裝,使用封裝後的數據進行分頁,首先我們寫一個函數去封裝這兩個對象,例如get_pagination_data:
def get_context_data(self, **kwargs):
context = super(ArticleListView, self).get_context_data(**kwargs)
paginator = context.get(‘paginator‘) # 包含整體數據的相關信息
page_obj = context.get(‘page_obj‘) # 包含當前頁數據相關的信息
pagination_data = self.get_pagination_data(paginator, page_obj)
context.update(pagination_data)
return context
def get_pagination_data(self, paginator, page_obj, around_count=2):
left_has_more = False
right_has_more = False
current_page = page_obj.number
if current_page <= around_count + 2:
left_range = range(1, current_page)
else:
left_has_more = True
left_range = range(current_page-around_count,current_page)
if current_page >= paginator.num_pages - around_count-1:
right_range = range(current_page+1, paginator.num_pages+1)
else:
right_has_more = True
right_range = range(current_page+1, current_page+around_count+1)
pagination_data = {
‘left_has_more‘: left_has_more,
‘right_has_more‘: right_has_more,
‘left_range‘: left_range,
‘right_range‘: right_range
}
return pagination_data
在模板使用封裝的數據,去進行分頁,示例代碼如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文章列表</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<ul>
{% for article in article_list %}
<li>
{{ article.title }}
</li>
{% endfor %}
<ul class="pagination">
{# 上一頁 #}
{% if page_obj.has_previous %}
<li><a href="{% url ‘front:article_list‘ %}?page={{ page_obj.previous_page_number }}">上一頁</a></li>
{% else %}
<li class="disabled"><a href="javascript:void(0);">上一頁</a></li>
{% endif %}
{# 中間左邊部分 #}
{% if left_has_more %}
<li><a href="{% url ‘front:article_list‘ %}?page=1">1</a></li>
<li><a href="javascript:void(0);">...</a></li>
{% for page in left_range %}
<li><a href="{% url ‘front:article_list‘ %}?page={{ page }}">{{ page }}</a></li>
{% endfor %}
{% else %}
{% for page in left_range %}
<li><a href="{% url ‘front:article_list‘ %}?page={{ page }}">{{ page }}</a></li>
{% endfor %}
{% endif %}
{# 中間部分當前頁 #}
<li class="active"><a href="{% url ‘front:article_list‘ %}?page={{ page_obj.number }}">{{ page_obj.number }}</a></li>
{# 中間右邊部分 #}
{% if right_has_more %}
{% for page in right_range %}
<li><a href="{% url ‘front:article_list‘ %}?page={{ page }}">{{ page }}</a></li>
{% endfor %}
<li><a href="javascript:void(0);">...</a></li>
<li><a href="{% url ‘front:article_list‘ %}?page={{ paginator.num_pages }}">{{ paginator.num_pages }}</a></li>
{% else %}
{% for page in right_range %}
<li><a href="{% url ‘front:article_list‘ %}?page={{ page }}">{{ page }}</a></li>
{% endfor %}
{% endif %}
{# 下一頁 #}
{% if page_obj.has_next %}
<li><a href="{% url ‘front:article_list‘ %}?page={{ page_obj.next_page_number }}">下一頁</a></li>
{% else %}
<li class="disabled"><a href="javascript:void(0);">下一頁</a></li>
{% endif %}
</ul>
</ul>
</body>
</html>
使用上述兩種方法基本可以完成分頁的業務需求
django視圖之分頁