有些功能独立的小功能,单独一篇文章不够分量,于是在这里集中解释了。
和读者常见问题帖一样,本篇是持续更新的,想到一个写一个。
文章快捷导航
快捷导航指的是这个功能:
点击对应按钮,页面立即跳转到另一篇文章中,省去了用户返回首页重新寻找文章的繁琐。
视图
实现本功能的关键就是要查找出发表时间与当前文章相邻的文章。为了演示简单,就粗略以id
作为发表时间的排序。
在之前的搜索文章的教程中,我们已经体验过contains
这种查找方法了,现在需要用到另外两种:gt
和lt
。
编写视图:
article/views.py
...
# 文章详情
def article_detail(request, id):
# 已有代码。取出相应的文章
article = ArticlePost.objects.get(id=id)
...
# 过滤出所有的id比当前文章小的文章
pre_article = ArticlePost.objects.filter(id__lt=article.id).order_by('-id')
# 过滤出id大的文章
next_article = ArticlePost.objects.filter(id__gt=article.id).order_by('id')
# 取出相邻前一篇文章
if pre_article.count() > 0:
pre_article = pre_article[0]
else:
pre_article = None
# 取出相邻后一篇文章
if next_article.count() > 0:
next_article = next_article[0]
else:
next_article = None
...
# 需要传递给模板的对象
context = {
...
'pre_article': pre_article,
'next_article': next_article,
}
执行逻辑如下:
lt
过滤出所有id
比当前文章小的文章- 对这些文章按
-id
进行排序 - 取出排在首位的文章,即相邻的文章
- 返回给模板上下文
gt
的原理也是类似。
模板
模板得到上下文后,就要相应修改:
templates/detail.html
...
<!-- 相邻文章导航 -->
<div class="row justify-content-end">
{% if next_article %}
<div class="col-auto mr-auto">
<a href="{{ next_article.get_absolute_url }}"
class="btn btn-info"
>
{{ next_article.title }}
</a>
</div>
{% endif %}
{% if pre_article %}
<div class="col-auto">
<a href="{{ pre_article.get_absolute_url }}"
class="btn btn-info"
>
{{ pre_article.title }}
</a>
</div>
{% endif %}
</div>
代码很简单,就是按照上下文的信息,将导航按钮正确显示出来。功能就完成了。
导航的逻辑不一定非要按时间排序,也可以按照热度、文章类别甚至文字个数,这个就随便你了。
页面定位
良好的UI设计应该让用户清楚自己当前的状态。
比如我的博客就是这样的:
可以清楚看到当前正位于【文章】-【编程】-【最近】这个页面中的。
实现方法提供给大家参考。
例子中的样式用的LayUI,而不是Bootstrap,但是思路是相同的
读者请尝试用Bootstrap实现
栏目和排序
栏目和排序都是被查询文章集合的共有属性,因此考虑在article_list()
视图中把它们作为上下文传递到模板中来,类似于某种“标记”:
/views.py
# 传递到模板的对象
context = { ..., 'column': column, 'order': order }
然后在模板中通过column
和order
的值,控制按钮的样式:
/list.html
<!-- 栏目 -->
<a ... class="
...
{% if column_id == column.id %}
layui-btn-warm
{% else %}
layui-btn-primary
{% endif %}
"
>...</a>
...
<!-- 排序 -->
<a ...>
{% if order == 'total_views' %}
<cite>最近</cite>
{% else %}
最近
{% endif %}
</a>
代码中的column_id
是当前页面所在的栏目,column.id
是视图传递给模板的上下文。通过比对这两个值是否一致,从而决定栏目按钮的样式。
面包屑也是类似的方法,判断是否需要插入<cite>
标签。
导航栏
就是我的博客顶部的“黑条”,它是所有板块的入口。
如果导航栏也采用类似上面的传递值给模板来定位,那么要求所有的app都要传递同一个”标记”到模板中。理论上可行,但是也会导致app之间耦合得太紧,个人感觉不是好的实践。
所以我采用了一种笨办法:直接在模板中读取当前的url,从而判断页面位置:
/header.html
...
<li class= "
...
{% if '/xxx' in request.path %}
layui-this
{% endif %}
"
>
...
这种方法有个小问题,就是如果url中恰好出现了别的板块的关键词,定位可能会显示错误。
不过对博客来说也不算什么大问题,比紧耦合的设计要好多了。
持续更新中…
- 有疑问请在杜赛的个人网站留言,我会尽快回复。
- 或Email私信我:dusaiphoto@foxmail.com
- 项目完整代码:Django_blog_tutorial