一 编写视图函数
# 没有登录的用户也可以访问这个函数
def article_detail(request, id, slug):
article = get_object_or_404(ArticlePost, id=id, slug=slug)
# total_views:记录文章访问量
# 一般通过“对象类型:对象ID:对象属性”来命名一个键
total_views = r.incr("article:{}:views".format(article.id))
# zincrby的原型是zincrby(name,amount,value):根据amount所设定的步长值增加有序集合(name)中的value的数值
# 实现了article_ranking中的article.id以步长1自增,
# 即文章访问一次,article_ranking就将文章id的值增1
r.zincrby('article_ranking', 1,article.id)
# 得到article_ranking中排序前10名对象
article_ranking = r.zrange('article_ranking', 0, -1, desc=True)[:10]
print(article_ranking)
# 得到前10名文章ID
article_ranking_ids = [int(id) for id in article_ranking]
print(article_ranking_ids)
# 查询出id在article_ranking_ids这个范围内的所有文章对象,并以文章对象为元素生成列表
most_viewed = list(ArticlePost.objects.filter(id__in=article_ranking_ids))
print(most_viewed)
# 对所得到的列表进行排序
most_viewed.sort(key=lambda x: article_ranking_ids.index(x.id))
# 将访问次数传递给模板,将最受欢迎文章列表传递给前端
return render(request, "article/list/article_detail.html",
{"article": article, "total_views": total_views,"most_viewed": most_viewed})
二 编写前端模板
{% extends "base.html" %}
{% load staticfiles %}
{% block title %}{{ article.title }}{% endblock %}
{% block content %}
<!-- with发起一个赋值操作,它的结尾部分是endwith,total_likes分别为点赞用户总数,total_likes在
这两部分圈定的范围内有效-->
{% with total_likes=article.users_like.count users_like=article.users_like.all %}
<div class="container">
<div class="col-md-9">
<header>
<h1>{{ article.title }}</h1>
<p>
<a href="{% url 'article:author_articles' article.author.username %}">
{{ article.author.username }}
</a>
<!-- pluralize的作用:如果total_likes为0或复数,则显示的是likes,如果total_likes为1,则显示like-->
<span style="margin-left:20px" class="glyphicon glyphicon-thumbs-up">{{ total_likes }}like{{ total_likes | pluralize }}</span>
<!-- 该文章总的访问此时-->
<span style="margin-left: 20px">{{ total_views }}view{{ total_views | pluralize }}</span>
</p>
</header>
<link rel="stylesheet" href="{% static 'editor/css/editormd.preview.css' %}"/>
<div id='editormd-view'>
<textarea id="append-test" style="display:none;">
{{ article.body }}
</textarea>
</div>
<div>
<!--点赞功能实现-->
<p class="text-center">
<a onclick="like_article({{article.id}}, 'like')" href="#"><span class="glyphicon glyphicon-thumbs-up">like</span></a>
<a onclick="like_article({{article.id}}, 'unlike')" href="#"><span style="margin-left: 15px;"
class="glyphicon glyphicon-thumbs-down">unlike</span></a>
</p>
</div>
<div>
<p class="text-center"><strong>点赞本文的读者</strong></p>
{% for user in article.users_like.all %}
<p class="text-center">{{ user.username }}</p>
{% empty %}
<p class="text-center">还没有人对此文章表态</p>
{% endfor %}
</div>
</div>
<div class="col-md-3">
<p class="text-center">
<h3>最受欢迎文章</h3></p>
<ol>
{% for article_rank in most_viewed %}
<li>
<a href="{{article_rank.get_url_path}}">{{ article_rank.title }}</a>
</li>
{% endfor %}
</ol>
</div>
</div>
<script src='{% static "js/jquery.js" %}'></script>
<script src='{% static "editor/lib/marked.min.js" %}'></script>
<script src='{% static "editor/lib/prettify.min.js" %}'></script>
<script src='{% static "editor/lib/raphael.min.js" %}'></script>
<script src='{% static "editor/lib/underscore.min.js" %}'></script>
<script src='{% static "editor/lib/sequence-diagram.min.js" %}'></script>
<script src='{% static "editor/lib/flowchart.min.js" %}''></script>
<script src='{% static "editor/lib/jquery.flowchart.min.js" %}'></script>
<script src='{% static "editor/editormd.js" %}'></script>
<script type="text/javascript" src="{% static 'js/layer.js'%}"></script>
<script type="text/javascript">
$(function(){
editormd.markdownToHTML("editormd-view", {
htmlDecode : "style,script,iframe", // you can filter tags decode
emoji : true,
taskList : true,
tex : true, // 默认不解析
flowChart : true, // 默认不解析
sequenceDiagram : true, // 默认不解析
});
});
function like_article(id,action){
$.ajax({
url: "{% url 'article:like_article' %}",
type: "POST",
data: {"id":id, "action":action},
success: function(e){
if(e=="1"){
layer.msg("感谢点赞");
window.location.reload();
}else{
layer.msg("我会继续努力");
window.location.reload();
}
},
});
}
</script>
{% endwith %}
{% endblock %}
三 测试