技术笔记——Django+Nginx+uwsgi搭建自己的博客(十)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/BetrayArmy/article/details/79835925

在本篇博客中,我们将继续围绕着Redis做文章。由于Redis的内存存储特性,其适合用于存储那些变动频繁的数据,如博客点赞数、站内消息等。我们在这篇博客中将实现用户消息系统,即当有人给博客点赞或发表评论时,博客作者将收到站内消息,且在主页上会看到目前未读的消息数目。若有未读的消息,则消息数会加粗显示

用户消息系统分为两部分:消息发布和消息管理。由于当博客被评论或被点赞都会发布消息,因此发布消息的操作是一个高频操作,我们使用redis来发布消息。

首先来修改myblog/settings.py,向其中加入名为RedisKey的字典,用于保存redis中key的各种后缀:

# myblog/settings.py
# ...
RedisKey = {'TITLEKEY':'title',
            'CONTENTKEY':'content',
            'READCOUNTKEY':'readcount',
            'COMMENTCOUNTKEY':'commentcount',
            'UNREADMSGKEY':'unreadmsg',
            'THUMBUPKEY':'thumbup',
            'THUMBCOUNTKEY':'thumbupcount',
            'READBLOGKEY':'readblog'
            }
# ...

然后我们在myblog目录下建立myutil.py文件,这个文件用于存储一些通用函数,这里我们加入generateKey函数,用于封装生成rediskey的操作:

# myblog/myutil.py
# -*- coding=utf-8 -*-

def generateKey(pkey,keykind):
    return str(pkey) + '_' + str(keykind)

由于每个用户可以同时收到多条消息,我们采用redis的list来存储消息。每当博客被评论或被点赞时,后台程序都会向这个用户所对应的消息列表中添加一条,并在之后的消息管理界面中显示出来。

我们修改blogs/views.py,向saveComment函数中添加以下代码:

# blogs/views.py
# ...
# Publish message to auther when new comment added(with redis)
        messagekey = generateKey(blog.auther.username,RedisKey['UNREADMSGKEY'])
        message_content = auther.username + u'评论了博客' + blog.title + u'于' + str(datetime.datetime.now())
        redis.lpush(messagekey,message_content)
# ...

在这里,我们使用刚才的generateKey函数生成每个用户的messagekey,为用户名_unreadmsg。因为用户名一定是唯一的,所以整个key的唯一性可以保证。message_content为要发表的消息内容,这里的auther.username为评论的作者的用户名,而不是博客的作者。在拼接好消息内容后,我们就可以使用redis.lpush函数将消息放入博客作者的消息列表中。lpush的含义是,将value放入key指向的list的最左边,即最新的消息永远是list的第一个元素。

我们已经实现了消息的发布,下面来看看如何显示信息以及处理信息。信息的显示包括在两个页面中:主页和用户资料页。在主页中,如果某个用户有了新的消息,其消息个数将会显示在用户名的旁边,并以加粗字体突出,如图所示:


可以看到,该用户有6条消息。点击“消息(6)”,可以进入消息管理页面查看每条消息,并可将所有消息设为已读:


点击“全部设置为已读”后,消息消失,主页的消息也不再加粗显示:



为了实现以上的功能,我们需要在Users App添加消息箱页面,以及修改主页的前端部分代码。首先来看Users App的消息箱代码:

# users/views.py
# ...
# messagebox
def messagebox(request):
    try:
        currentUser = Users.objects.get(username=request.session['username'])
        pool = ConnectionPool(host='localhost', port='6379', db=0)
        redis = StrictRedis(connection_pool=pool)
        messagekey = generateKey(currentUser.username,RedisKey['UNREADMSGKEY'])
        if redis.exists(messagekey):
            infos = redis.lrange(messagekey,0,redis.llen(messagekey)-1)
            msginfos = []
            for msg in infos:
                msg = msg.decode()
                msginfos.append(msg)
            messages = {'infos': msginfos}
        else:
            messages = {}

    except Exception as e:
        messages = {}
    return render(request,'users/messagebox.html',messages)

def setreaded(request):
    try:
        currentUser = Users.objects.get(username=request.session['username'])
        messagekey = generateKey(currentUser.username, RedisKey['UNREADMSGKEY'])
        pool = ConnectionPool(host='localhost', port='6379', db=0)
        redis = StrictRedis(connection_pool=pool)
        if redis.exists(messagekey):
            redis.delete(messagekey)
    except Exception as e:
        pass
    return HttpResponseRedirect(reverse('users:messagebox'))
# ...

messagebox为消息箱函数。该函数的作用就是从redis中拿到当前用户的消息列表,并将其渲染到前端;而对于没有消息的用户,则传入一个空字典作为渲染参数。我们使用redis.lrange(key,start,end)函数来拿到消息列表中的所有元素。该函数的作用为,从key所指向的list中拿取从start到end的元素,这里我们要拿取全部元素,因此start为0,end为llen(messagekey)-1,llen为消息列表的长度。

setreaded为全部设置为已读的函数,该函数的作用是清空当前用户的消息列表,直接使用redis.delete就好。

我们要在users/urls.py为这两个函数添加url:

# users/urls.py
# ...
urlpatterns = [
    # ...
    url(r'^messagebox/$',views.messagebox,name='messagebox'),
    url(r'^setreaded/$',views.setreaded,name='setreaded')
]

然后我们要编写消息箱前端部分的代码。在Users App的页面文件夹中添加messagebox.html,输入以下代码:

<!--messagebox.html-->
{% extends "userTemplate.html" %}
{% block content %}
<div id="content" class="list">
<a href="{% url 'users:setreaded' %}" >全部设置为已读</a>
{% if infos %}
	<ul>
	{% for info in infos %}
		<div class="articlelist">
                {{ info }}
		</div>
	{% endfor %}
	</ul>
{% else %}
	<p>没有消息</p>
{% endif %}
</div>
{% endblock %}

同时修改userTemplate.html,为消息箱添加入口:

<!--userTemplate.html-->
<!--......-->
<span><a href="{% url 'users:messagebox' %}">消息箱</a></span>
<!--......-->

最后,修改myblog/index.html,在主页上显示消息个数并加粗:

<!--index.html-->
<!--......-->
{% block nav %}
<a href="{% url 'index' %}">首页</a>
{% if curruser.username  == "anony" or curruser.username  == "" %}
<a href="{% url 'users:userregister' %}">用户注册</a>
<a href="{% url 'users:userlogin' %}">用户登录</a>
{% else %}
用户:{{ curruser.username }}
<a href="{% url 'users:messagebox' %}">
{% if  msgcount  != 0 %}
<strong>消息({{ msgcount }})</strong>
{% else %}
消息({{ msgcount }})
</a>
{% endif %}
<a href="{% url 'users:logoff' %}">退出登录</a>
<a href="{% url 'blogs:addblog' %}">写博文</a>
{% endif %}
{% endblock %}
<!--......-->

这里为了能使大家看清新加代码的位置,我把nav块的代码一并放上来,其中加粗部分是我们要新加的代码。当然,我们还要修改myblog/views.py中的index函数,把msgcount渲染到前端:

# myblog/views.py/index
# ...
    messagekey = generateKey(username,RedisKey['UNREADMSGKEY'])
    if redis.exists(messagekey):
        msgcount = redis.llen(messagekey)
    else:
        msgcount = 0
    pool.disconnect()
    content = { 'blog_list':blogList,
                'curruser':user,
                'msgcount':msgcount
               }
# ...

这样,我们就实现了用户消息系统。此时,若你的博客被人评论,则在主页上会看到有未读消息的显示。

在这篇博文中,我们使用redis实现了一个简单的用户消息系统。在下篇博文中,我们将继续使用redis实现博客的点赞功能,并且使用cookie修复一个博客阅读数被重复统计的bug,希望大家继续关注~

猜你喜欢

转载自blog.csdn.net/BetrayArmy/article/details/79835925