1. 程式人生 > >django視圖之分頁

django視圖之分頁

false 對象 內容 數據 next 分類信息 war 類信息 anon

在網站開發時,肯定會遇到分頁的事情需要處理,在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視圖之分頁