您现在的位置是:网站首页>>编程开发编程开发

Django个人博客开发(九)文章点击次数

发布时间:2018-04-14 12:04:15分类:编程开发阅读:1319

    概述

    每阅读一次文章,文章点击次数加一,为了不频繁进行数据库的读写,操作文章点击次数,使用redis键值对缓存文章点击次数。

    阅读文章时,要实时更新点击次数;显示文章列表或详情时,要获取当前文章点击次数;要永久保存文章点击次数,则需要将缓存同步到数据库中。因此,对文章点击次数的操作主要可分为三个部分:

    1)更新当前文章点击次数,upadate_article_hits()

    2)获取当前文章点击次数,get_article_hits()

    3)同步所有文章点击次数,syn_article_hits()

    更新和获取文章点击次数是针对当前文章对象,因此可以定义文章的数据模型方法,这样文章的实例对象可以直接调用方法更新或获取其点击次数。

    文章点击次数思路


    1、准备redis环境

    Redis服务器环境搭建网上搜索。

    2、在xdsite/settings.py中配置以redis作为djangocache缓存后端

    # Cache
    # cache 配置为Redis Backends
    CACHES = {
        "default": {
            "BACKEND": "django_redis.cache.RedisCache",
            "LOCATION": "redis://127.0.0.1:6379/1",
            "OPTIONS": {
                "CLIENT_CLASS": "django_redis.client.DefaultClient",
            }
        }
    }

    3、在blog应用目录下创建缓存管理的pythoncache_manager

    目录结构如下:


    其中,

    __init__.pypython包必需的文件,其中定义了__all__变量,指定了update_article_hitsget_article_hits两个函数,用于在导入包时,直接导入这两个方法,实现模糊导入;

    Cache_manager.py 中定义了update_article_hits()get_article_hits()两个函数,针对缓存操作文章点击次数;

    Cache_sync.py 中定义了syn_article_hits()函数,用于同步缓存与数据库的点击次数;

    注意:

    因为syn_article_hits()函数需要对文章数据模型Article操作,而update_article_hits()get_article_hits()两个函数需要在文章数据模型方法中调用,为了避免冲突,因此将syn_article_hits()与另外两个函数分作两个文件。

    4、编辑cache_manager.py文件

    # -*- encoding: utf-8 -*-
    from django.core.cache import cache
    
    def update_article_hits(article):
        """更新文章点击次数"""
        # 指定key不存在则从数据库hits字段添加,并设置永不过期
        cache.add("article:{}:views".format(article.id), article.hits, timeout=None)
    
        # 指定key的值自增1
        cache.incr("article:{}:views".format(article.id))
    5、编辑cache_sync.py文件

    # -*- encoding: utf-8 -*-
    from blog.models import Article
    from django.shortcuts import get_object_or_404
    from django.core.cache import cache
    
    def syn_article_hits():
        """将redis缓存中的点击次数同步到数据库中"""
        for key in cache.keys("article:*:views"):
            # 从key中获取文章id值
            article_id = int(key.split(':')[1])
            try:
                article = get_object_or_404(Article, id=article_id)
                # 如果数据库中的点击次数大于缓存的值,则更新缓存中的值,否则将缓存中的值存入数据库中
                if article.hits > int(cache.get(key)):
                    cache.set(key, article.hits)
                else:
                    article.hits = int(cache.get(key))
                    article.save()
            except:
                # 数据库中已不存在该文章则redis删除该键
                cache.delete(key)

    6、编辑__init__.py文件

    __author__ = 'xdao07'
    from .cache_manager import update_article_hits, get__article_hits
    
    __all__ = [
        "update_article_hits", "get__article_hits"
    ]
    7、在文章数据模型Article中,定义数据模型方法

    from .cache_manager import get__article_hits, update_article_hits
    # 文章表数据模型
    class Article(models.Model):
        ……省略部分……
        # 更新缓存中的文章点击次数
        def update_hits(self):
            update_article_hits(self)
    
        # 从缓存获取文章点击次数
        def get_hits(self):
            return get__article_hits(self)
    8、在文章详情视图views.py/article_detail()中添加文章对象方法,实时更新文章点击次数

    # 文章详情页视图
    def article_detail(request, id, slug):
        # 返回匹配id和slug的文章对象,否则的404错误
        article = get_object_or_404(Article, id=id, slug=slug)
        # 更新当前文章点击次数
        article.update_hits()
        return render(request, 'blog/article.html', locals())
    9、在文章列表和文章详情模板页中完善文章阅读次数显示

    9.1文章列表,文件blog/baseblock/list.html

    <p class="dateview"><span>{{ article.publish | date:'Y-m-d' }}</span><span>阅读:{{ article.get_hits }}次</span><span>个人博客:[<a href="{% url 'blog:article_list' article.category.id %}">{{ article.category.name }}</a>]</span></p>
    9.2文章详情,文件blog/article.html

    <p class="box_p"><span>发布时间:{{ article.publish | date:'Y-m-d H:m:s' }}</span><span>分类:{{ article.category.name }}</span><span>阅读:{{ article.get_hits }}</span></p>
    10、把同步文章点击次数添加到文章列表页视图,在每次请求列表时将缓存中的点击次数同步到数据库(不提倡,依旧频繁读取库)

    from .cache_manager import cache_sync
    def article_list(request, category_id=None, tag_id=None, page=1):
        # 同步缓存和数据库中的文章点击次数
    cache_sync.syn_article_hits()
    ……省略部分……
    11、在RUL路由配置文件blog/urls.py中指定一个接口,用于手动和添加计划任务更新文章点击次数(注释掉10中添加的cache_sync.syn_article_hits()行)

    11.1 在视图文件blog/views.py中添加视图函数

    from django.http import HttpResponse
    from .cache_manager import cache_sync
    # 同步缓存和数据库中的文章点击次数
    def sync_hits_cache_to_db(request):
        cache_sync.syn_article_hits()
        # 返回指定字符串到客户端
    return HttpResponse('Sync hits between cache and db.')
    11.2 URL路由文件blog/urls.py中添加路由

    urlpatterns = [
    	……省略部分……
        # 通过指定路由到指定视图将执行同步函数
        url(r'^sync-hits-cache-to-db/$', views.sync_hits_cache_to_db, name='sync_hits_cache_to_db'),
    ]

    11.3 重启项目,检测路由是否能同步点击次数

    代码查看:https://github.com/xdao07/xdsite/tree/v0.0.6

    代码下载:git clone --branch v0.0.6 https://github.com/xdao07/xdsite.git