Wagtail 教程 8:使用 Django 缓存

2019年1月16日


# Wagtail # Django # Python
  • Wagtail 是一个用 Python 编写的开源 CMS,基于 Django 框架构建。 它优雅、强大、敏捷,专注于灵活性和用户体验,为开发人员提供一个快速有吸引力的界面,可以直观地创建和组织内容。
  • Wagtail 教程系列 记录了基于 Wagtail 搭建博客站点的整个过程,当前站点 所呈现的即是搭建过程的最新效果。

安装 django-redis

pip install django-redis

配置 Django Cache Setting

CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': '127.0.0.1:6379',
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
        }
    }
}

缓存模板页面

可以对整个模板页面缓存:

{% cache 691200 blog_index request.get_full_path request.preview_timestamp %}
<!-- 691200 = 8 days. The next 2 arguments make sure the fragment
 is cached for a specific URL (there are index pages for each tag and category)
  and can be identified in the cache table easily. The last argument is to allow wagtail page previews  -->

<!DOCTYPE html>
<html lang="zh_cn">

    ...

</html>
{% endcache %}

也可以对模板页面局部缓存:

<!-- blog index page template example -->
{% extends "base.html" %}
{% load blog_tags cache %}

{% block content %}
{% cache 691200 blog_index request.get_full_path request.preview_timestamp %}
<!-- 691200 = 8 days. The next 2 arguments make sure the fragment
 is cached for a specific URL (there are index pages for each tag and category)
  and can be identified in the cache table easily. The last argument is to allow wagtail page previews  -->
     {% include 'spotlight_hero.html' %}
     {% category_menu_strip category %}

<section>
  <div class="container">
    <div class="row">
      <div class="col-sm-12">

    {% for rl in self.related_links.all %}
    <!-- NOTE: this is where the queryset is evaluated, so this database hit will be cached -->
        <p>{{ rl.title }}: <a href='{{ rl.link_page.url }}'>{{ rl.link_page }}</a></p>
    {% endfor %}

        <div class="row">
        {% for blog in blogs %}
                {% include 'blog/blog_post.html' %}
        {% endfor %}
        </div>

      </div>
    </div>
  </div>
</section>
{% endcache %}
{% endblock %}

预览Wagtail 实时页面效果

我们在预览时向缓存签名添加时间戳,以便我们实际看到预览而不是相同URL的缓存:

# Add this to each of your page models to over ride their serve_preview method

class MyPage(Page):
    # your other class stuff here
    def serve_preview(self, request, mode_name):
        request.preview_timestamp = datetime.now()
        return super(MyPage, self).serve_preview(request, mode_name)

缓存刷新(创建/删除)

用编码方式来访问所有需要刷新的页面以自动创建缓存,重建缓存时需要先删除缓存:

# in my /slowread/slowread/utils.py
# I will want to use this in a management command as well as a view
import requests
from wagtail.core.models import Page
from django.core.cache import cache

def request_all_pages():

    try:
        # 访问 / 主页
        print("访问 主页 http://localhost")
        requests.get("http://localhost")

        # 访问 /blog
        print("访问 博客列表页 http://localhost/blog")
        requests.get("http://localhost/blog")

        # 访问 /blog/*
        page = Page.objects.get(title="文章列表")
        blogpages = page.get_children().live().order_by('-first_published_at')
        for blogpage in blogpages:
            print("访问 文章 " + blogpage.full_url)
            requests.get(blogpage.full_url)

        # 访问 /wallpaper
        print("访问 博客列表页 http://localhost/wallpaper")
        requests.get("http://localhost/wallpaper")

    except Exception as e:
        print("Unexpected Error: {}".format(e))

# 默认情况下,Django的模板缓存使用名为“template.chache.”前缀键名
def clear_page_cache():
    # just clears all template fragment caches
    try:
        cache.delete_pattern("template.cache.*")
        print("Page Cache deleted...")
    except Exception as e:
        print("Unexpected Error: {}".format(e))

将“刷新缓存”加入 Wagtail 设置菜单

# Create your views here.
# in /slowread/slowread/blog/views.py

from django.shortcuts import render
from django.contrib import messages
from django.shortcuts import redirect
from django.contrib.auth.decorators import login_required
from slowread.utils import request_all_pages, clear_page_cache

@login_required()
def RefreshPageCache(r):
    try:
        clear_page_cache()
        request_all_pages()
        messages.success(r, 'Page Cache has been refreshed!')

    except Exception as e:
        messages.error(r, e )
    return redirect('/admin/')
# in /slowread/slowread/blog/wagtail_hooks.py

from wagtail.admin.menu import MenuItem
from wagtail.core import hooks

@hooks.register('register_settings_menu_item')
def register_refresh_cache_menu_item():
    return MenuItem('刷新缓存', '/blog/refresh-cache', classnames='icon icon-folder-inverse', order=1)

修改 /slowread/urls.py ,增加 刷新缓存 url:

from django.urls import path
from slowread.blog.views import RefreshPageCache
urlpatterns = [
    ...
    # 刷新 缓存
    path('blog/refresh-cache/', RefreshPageCache, name='refresh cache'),
    ...
]