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

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

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

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

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

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


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

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

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

{% extends "base.html" %}

{% block title %}杨仕航的博客{% endblock %}
{% block blog_active %}active{% endblock %}
{% block extra_head %}
    <link rel="stylesheet" type="text/css" href="/static/css/global/blog.css">
    {% block blog_head %}{% endblock %}
{% endblock %}

{% block content %}
        <div class="col-md-9 col-xs-12">
            {% block blog_content%}
                {# 博文列表和博文文章 #}
            {% endblock %}
        </div>

        {#侧边栏#}
        <div class="col-md-3 col-xs-12 blog-border">
            <div class="side-list">
                <h4>
                    <span class="glyphicon glyphicon-book"></span>
                    随机推荐
                </h4>
                <ul>
                    {% for blog in rand_blogs %}
                        <li>
                            <a href="{%url 'detailblog' blog.id%}" target="_blank">
                                {{blog.caption}}
                            </a>
                        </li>
                    {% endfor %}
                </ul>  
            </div>          
        </div>
{% endblock %}

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

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


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

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

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

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


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

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

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


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

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

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

def rand_blogs(except_id=0):
    #随机获取 10+1
    rand_count = 10
    blogs = random.sample(Blog.objects.all(), rand_count + 1)

    #去掉要排除的博文
    blogs_id = map(lambda x:x.id, blogs)
    if blogs_id.count(except_id)>0:
        #移除排除的博文
        blogs.pop(blogs_id.index(except_id))

    #返回前10篇
    return blogs[:rand_count]

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

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

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

加上rand_blogs参数的返回数据:

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

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

20170106/20170106162706844.png

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




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

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

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

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

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

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

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

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

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

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

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

评论列表

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

新的评论

清空