文章

Django - 分頁與快取

今天我們將學習如何在 Django 中實現分頁和快取功能。分頁可以有效地將大量數據分成多頁顯示,而快取則能夠顯著提高網站的性能,減少對資料庫的頻繁查詢。


課程目標

  • 瞭解 Django 分頁系統的基本用法。
  • 學會實現分頁功能並在前端顯示分頁按鈕。
  • 探索 Django 快取框架,實現快取優化數據讀取。
  • 瞭解不同的快取配置選項及其應用場景。

課程內容

1. 分頁

1.1 為什麼需要分頁?

當數據量較大時,將所有數據一次性加載到頁面中可能會導致以下問題:

  • 加載速度變慢。
  • 用戶體驗差。
  • 增加伺服器負載。

1.2 分頁類 (Paginator)

Django 提供了內建的 Paginator 類來輕鬆實現分頁功能。

示例代碼:分頁實作views.py 中實現分頁邏輯:

1
2
3
4
5
6
7
8
9
10
11
12
from django.core.paginator import Paginator
from django.shortcuts import render
from myapp.models import Article

def article_list(request):
    articles = Article.objects.all()  # 獲取所有文章
    paginator = Paginator(articles, 5)  # 每頁顯示 5 篇文章

    page_number = request.GET.get('page')  # 獲取當前頁碼
    page_obj = paginator.get_page(page_number)  # 獲取當前頁數據

    return render(request, 'article_list.html', {'page_obj': page_obj})

模板代碼:顯示分頁按鈕article_list.html 中添加分頁按鈕:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{% for article in page_obj %}
<h2>{{ article.title }}</h2>
<p>{{ article.content }}</p>
{% endfor %}

<div class="pagination">
  {% if page_obj.has_previous %}
  <a href="?page={{ page_obj.previous_page_number }}">上一頁</a>
  {% endif %}

  <span
    >第 {{ page_obj.number }} 頁,共 {{ page_obj.paginator.num_pages }} 頁</span
  >

  {% if page_obj.has_next %}
  <a href="?page={{ page_obj.next_page_number }}">下一頁</a>
  {% endif %}
</div>

2. 快取

2.1 為什麼需要快取?

快取能夠提高網站性能,減少以下問題:

  • 資料庫查詢頻繁。
  • 重複執行耗時的操作。
  • 頁面加載速度慢。

2.2 快取的類型

Django 支持以下幾種快取類型:

  • 基於內存的快取(本地內存或共享內存)。
  • 文件系統快取(將快取數據儲存於文件)。
  • 數據庫快取(使用資料庫儲存快取數據)。
  • 第三方快取後端(如 Redis 或 Memcached)。

2.3 啟用快取

settings.py 中配置快取:

1
2
3
4
5
6
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        'LOCATION': 'unique-snowflake',
    }
}

2.4 使用快取

快取整個視圖 使用裝飾器來快取視圖的回應:

1
2
3
4
5
6
from django.views.decorators.cache import cache_page

@cache_page(60 * 15)  # 快取時間為 15 分鐘
def my_view(request):
    # 耗時邏輯
    return render(request, 'my_template.html', {'data': data})

快取模板片段 快取模板的特定部分:

1
2
3
4
5
{% load cache %} {% cache 600 sidebar %}
<div class="sidebar">
  <!-- 假設這部分內容生成耗時 -->
</div>
{% endcache %}

3. 分頁與快取的結合

當數據量大時,分頁與快取可以結合使用,避免重複查詢。

3.1 分頁數據的快取

將分頁數據進行快取:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from django.core.cache import cache

def cached_article_list(request):
    page_number = request.GET.get('page', 1)
    cache_key = f"articles_page_{page_number}"

    # 從快取中嘗試獲取數據
    articles = cache.get(cache_key)

    if not articles:
        # 如果快取中沒有數據,從資料庫查詢並儲存到快取
        articles = Article.objects.all()[(int(page_number) - 1) * 5:int(page_number) * 5]
        cache.set(cache_key, articles, 60 * 15)

    return render(request, 'article_list.html', {'articles': articles})

4. 高級主題:基於 Redis 的快取

Redis 是一種高效的快取後端,適合用於高流量網站。

4.1 安裝 Redis

首先安裝 Redis 伺服器和 Python 客戶端:

1
pip install django-redis

4.2 配置 Redis

settings.py 中設置 Redis 為快取後端:

1
2
3
4
5
6
7
8
9
CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/1',
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
        },
    }
}

5. 本日總結

  • 學習 Django 分頁的基本用法,並實現分頁按鈕。
  • 瞭解 Django 快取框架的配置與應用。
  • 將分頁與快取結合,提高了效率。
  • 學會使用 Redis 作為高效的快取後端。

作業

  1. 為昨天的 Blog 系統添加分頁功能,設置每頁顯示 10 篇文章。
  2. 為 Blog 系統的首頁啟用視圖級別的快取,快取時間設為 10 分鐘。
  3. 使用 Redis 作為快取後端,測試其性能提升。

本文章以 CC BY 4.0 授權