Django搭建个人博客:根据浏览量对最热文章排序
有了浏览量之后,文章受欢迎的程度就有了评价标准。随之而来的就有根据浏览量对文章进行排序的需求,即显示“最热文章”。
现在你已经很熟悉MTV模式,不需要我啰嗦也能完成任务:
- 文章的模型已经有了,不需要写Model了
- 写一个视图函数
article_list_by_views()
,取出按浏览排序后的文章对象 - 将文章对象传递到模板,并进行渲染
很简单,但也隐藏着问题:最热文章列表和之前的普通文章列表相比,大部分功能其实都是相同的,仅仅是排序不同而已。
万一哪天需要根据文章标题排序呢?万一还需要用户id排序、标签排序、收藏排序...不仅如此,就连路由urls.py
都要跟着膨胀。代码会越来越臃肿且不可维护。
重复的代码是万恶之源。因此这里挑战一下,不创建新的视图/路由,而是将排序功能融合到已有的视图/路由中。
视图
根据以上需求,重写article_list()
:
article/views.py ... # 重写文章列表 def article_list(request): # 根据GET请求中查询条件 # 返回不同排序的对象数组 if request.GET.get('order') == 'total_views': article_list = ArticlePost.objects.all().order_by('-total_views') order = 'total_views' else: article_list = ArticlePost.objects.all() order = 'normal' paginator = Paginator(article_list, 3) page = request.GET.get('page') articles = paginator.get_page(page) # 修改此行 context = { 'articles': articles, 'order': order } return render(request, 'article/list.html', context)
重点知识如下:
- 前面用过GET请求传递单个参数。它也是可以传递多个参数的,如
?a=1&b=2
,参数间用&
隔开 - 视图根据GET参数
order
的值,判断取出的文章如何排序 order_by()
方法指定对象如何进行排序。模型中有total_views
这个整数字段,因此‘total_views’为正序,‘-total_views’为逆序- 为什么把新变量
order
也传递到模板中?因为文章需要翻页!order
给模板一个标识,提醒模板下一页应该如何排序
这样一来,排序所需要的参数都可以通过查询获得,连urls.py
都不用改写了。
模板
接下来修改文章列表模板:优化入口,并且正确分页:
templates/article/list.html ... <div class="container"> <nav aria-label="breadcrumb"> <ol class="breadcrumb"> <li class="breadcrumb-item"> <a href="{% url 'article:article_list' %}"> 最新 </a> </li> <li class="breadcrumb-item"> <a href="{% url 'article:article_list' %}?order=total_views"> 最热 </a> </li> </ol> </nav> <div class="row mt-2"> {% for article in articles %} ... {% endfor %} </div> <!-- 页码导航 --> ... <a href="?page=1&order={{ order }}" class="btn btn-success">« 1</a> ... <a href="?page={{ articles.previous_page_number }}&order={{ order }}" class="btn btn-secondary">...</a> ... {% if articles.has_next %} <a href="?page={{ articles.next_page_number }}&order={{ order }}" class="btn btn-secondary">{{ articles.next_page_number }}</a> ... <a href="?page={{ articles.paginator.num_pages }}&order={{ order }}" class="btn btn-success">{{ articles.paginator.num_pages }} »</a> ...
- 新增了Bootstrap中的面包屑导航样式
breadcrumb
- 页码导航中,所有的分页链接都新增了
order
参数
测试
启动服务器,点击“最热”:
工作得很好!切换页码,留意地址栏中是如何变化的。
还剩一个小瑕疵:用户点击“最热”按钮后,此按钮最好能够变为灰色,并且不可点击。这个精益求精的机会就留给读者去优化吧。
header.html中有一个小改动:"写文章"的入口被挪到用户下拉菜单中了。
总结
本章已经摸到一个高级的编程领域门槛了:代码复用。将类似功能的代码合并到了一起,并且让后续的功能扩展变得很容易。只需要在视图中写几个elif
语句就搞定了。
在读者以后的编程中,也要尽量优化代码结构,达到事半功倍的效果。
至此,博客虽小,功能却相当完整了。继续努力!
- 有疑问请在杜赛的个人网站留言,我会尽快回复。
- 或Email私信我:[email protected]
- 项目完整代码:Django_blog_tutorial
转载请注明出处。
相关推荐
zlxcsdn 2020-09-13
listep 2020-09-11
jokewinl 2020-07-18
liuyang000 2020-04-25
rein0 2020-04-18
wordmhg 2020-04-09
wangqing 2020-04-06
chaoxiao 2020-03-07
horizonheart 2020-02-16
adonislu 2020-02-14
sschencn 2020-02-14
嗡汤圆 2020-02-02
yuanran0 2020-01-30
shawsun 2020-01-20
wuxiaosi0 2020-01-08
yedaoxiaodi 2020-01-04
zhglinux 2020-01-03
程松 2020-01-01