Django Blog 文章按发表时间自动归档的优雅解决方案
Blog 应用通常都有一个文章归档的功能,按照年月来对所有文章分组,比较优雅的显示可能是这样的:
- 2016 年
- 8 月
- 4月
- 3月
- 2015 年
- 9月
- 8月
- 1月
- 2013 年
- 7月
- 6月
- 5月
Django 为上述的需求提供了非常优雅的解决方案。
假设我们有如下的 Model :
models.py
class Post(models.Model):
"""
Blog 的文章模型
"""
title = models.CharField(max_length=255)
body = models.TextField()
pub_date = models.DateTimeField()
def __str__(self):
return self.title
其中 pub_date
是文章发表时间。首先我们取得所有已发表文章的发表时间(pub_date,精确到月份):
views.py
def archive(request):
# datetimes() 方法返回一个 python 的 datetimes 对象列表
# 对应着每篇文章的发表时间
# month 表示精确到月份,DESC 表示降序排列
dates = Post.objects.datetimes('pub_date', 'month', order='DESC')
return render(request,'archive.html',{'dates':dates})
例如你可能得到如下的 datetimes 对象列表:
2016 08
2016 04
2016 03
2015 09
2015 08
2015 01
2013 07
2013 06
2013 05
已经按照先年份后月份降序排列,现在需要做的就是按照年份分组即可,Django 为我们提供了 {% regroup %} 模板标签,在模板中使用它:
archive.html
<p>归档</p>
<!-- 归档 -->
<!--
regroup 对 dates 按照 year(年份) 分组,把相同年份的月分到一个组
-->
{% regroup dates by year as dates_by_year %}
<ul>
{% for mouth in dates_by_year %}
<!-- month 是一组月份列表 -->
<li>
{{ mouth.grouper }} 年
<!-- grouper 是组头,即某个月份列表的年份 -->
<ul>
{% for d in mouth.list %}
<!-- 再循环显示该年份组下的月份列表即可 -->
<li>
{{ d |date:'m' }} 月
</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
测试效果如图:
由此实现了按照文章发表时间自动归档,通过 datetimes() 方法的参数还可以控制归档的精度,比如日、时、分等,简洁而优雅。归档的样式则可以通过 css 自由定制。