我的网站搭建(第39天) 博文随机推荐

  • 发布时间:2017年1月6日 16:28
  • 作者:杨仕航
* 该文是基于Python2.7开发的,最新Python3.x和Django2.x视频教程可以前往 >> Django2.0视频教程

在我的博客列表页面中,每页显示12篇博文。随着博文发表越来越多,很多文章自然而然地被藏在深处。

这样不利于展示我的博客内容。所以需要提高博文的曝光率。

提高博文的曝光率常见地方法是文章推荐。我准备开发两种:随机推荐和猜你喜欢。

随机推荐很好处理,而猜你喜欢需要分析用户行为。先看看随机推荐如何实现。


遵循先前端,再后端,最后反馈前端的开发流程。

为了SEO优化,就不采用ajax的方式获取随机推荐博文的文章列表。考虑直接输出到页面,而需要输出到页面的有两个地方:博客列表和博文文章。

刚好我这两个模版页面的父级页面都是同一个,修改该父级页面即可。打开该模版页面,修改如下代码:

  1. {% extends "base.html" %}
  2.  
  3. {% block title %}杨仕航的博客{% endblock %}
  4. {% block blog_active %}active{% endblock %}
  5. {% block extra_head %}
  6.     <link rel="stylesheet" type="text/css" href="/static/css/global/blog.css">
  7.     {% block blog_head %}{% endblock %}
  8. {% endblock %}
  9.  
  10. {% block content %}
  11.         <div class="col-md-9 col-xs-12">
  12.             {% block blog_content%}
  13.                 {# 博文列表和博文文章 #}
  14.             {% endblock %}
  15.         </div>
  16.  
  17.         {#侧边栏#}
  18.         <div class="col-md-3 col-xs-12 blog-border">
  19.             <div class="side-list">
  20.                 <h4>
  21.                     <span class="glyphicon glyphicon-book"></span>
  22.                     随机推荐
  23.                 </h4>
  24.                 <ul>
  25.                     {% for blog in rand_blogs %}
  26.                         <li>
  27.                             <a href="{%url 'detailblog' blog.id%}" target="_blank">
  28.                                 {{blog.caption}}
  29.                             </a>
  30.                         </li>
  31.                     {% endfor %}
  32.                 </ul>  
  33.             </div>          
  34.         </div>
  35. {% endblock %}

其中,侧边栏部分的代码是我新增的。

我需要传递rand_blogs数据给该页面,再循环遍历输出。rand_blogs是随机博客的列表。


初步加上前端代码之后,再修改后端代码,产生随机博客列表。

添加该功能代码之后,还需要考虑一个问题:对于随机产生的博客列表中,怎么剔除当前博文

若在博客列表页面,就无需剔除,因为当前没有打开某一篇文章。

若打开了某一篇文章,就需要剔除该篇文章。避免重复显示。


一开始,想到的方法是先随机获取10篇博文。判断这10篇博文是否有包含当前打开的文章。若包含,则剔除,再继续随机获取多一篇文章。而且还需要判断这篇文章是否为当前打开的文章,直到不等于当前打开的文章为止。

这种做法效率不高。后来脑筋一转,想到另外一个思路。

我可以先获取11篇博文。判断这11篇博文是否包含当前打开的文章,若包含,则剔除,还剩下10篇博文。若不包含,再取前10篇文章即可。


打开blog应用的views.py文件,添加引用:

  1. #coding:utf-8
  2. from apps_project.blog.models import Blog #博客对应的模型
  3. import random #随机数模块

添加获取前10篇随机博文的方法:

  1. def rand_blogs(except_id=0):
  2.     #随机获取 10+1
  3.     rand_count = 10
  4.     blogs = random.sample(Blog.objects.all(), rand_count + 1)
  5.  
  6.     #去掉要排除的博文
  7.     blogs_id = map(lambda x:x.id, blogs)
  8.     if blogs_id.count(except_id)>0:
  9.         #移除排除的博文
  10.         blogs.pop(blogs_id.index(except_id))
  11.  
  12.     #返回前10篇
  13.     return blogs[:rand_count]

响应博客列表的方法中,加上rand_blogs参数的返回数据:

  1. #返回随机推荐的博文 (我这里用一个字典记录,再返回。根据自己的实际情况自行修改)
  2. data['rand_blogs'] = rand_blogs()

响应某篇博文的方法中,也

加上rand_blogs参数的返回数据:

  1. #返回随机推荐的博文 (我这里用一个字典记录,再返回。根据自己的实际情况自行修改)
  2. #id是该方法获取到的当前打开文章的id,通过根据实际情况修改
  3. data['rand_blogs'] = rand_blogs(id)

保存,运行可看到如下效果:

20170106/20170106162706844.png

最后,再反馈前端。这里主要修改该侧边栏的样式即可。




多谢网友“杨学光”的建议。他建议随机排序的方法如下:

  1. def rand_blogs(except_id=0):
  2.     rand_count = 10
  3.     return Blog.objects.exclude(id=except_id).order_by('?')[:rand_count]

先用exclude排除当前打开博文,exclude相当于“不等于”条件。

再使用order_by('?')随机排序。这个方法我不知道,测试一下。发现确实可以这么处理。

最后才用切片器取前10条博客。

我在shell下测试,看到sql语句如下(select部分我用*代替全部字段):

  1. SELECT "blog_blog".*
  2. FROM "blog_blog"
  3. WHERE NOT ("blog_blog"."id" = 1)
  4. ORDER BY RANDOM() ASC
  5. LIMIT 10;

其中,order_by('?')对应 order by random()。

我推荐杨学光这种方法。因为执行效率要比我上面的方法高,直接执行SQL语句一步到位。

上一篇:机器学习03:k-近邻算法拓展和总结

下一篇:机器学习02:k-近邻算法综合使用

评论列表

智慧如你,不想发表一下意见吗?

新的评论

清空

公告 & 打赏

>>

欢迎打赏支持我 ^_^

最新公告

我把服务器搬到国内了,并做了一些优化,速度爆快

2021-09-22

了解更多