Django 基于年/月的文章归档
我刚开始学习Django,正在做一个应用程序。我已经完成了模型、视图和模板,但我想在页面底部添加一个归档功能,类似于这个http://www.flickr.com/photos/ionutgabriel/3990015411/。
我想列出所有的年份,然后在每个年份旁边列出该年的所有月份。那些有文章的月份要做成链接,没有文章的月份则不做链接。另外,我还想把月份的名称翻译成罗马尼亚语。
到目前为止,我做了以下工作:
在我的视图中:
def archive(request):
arch = Post.objects.dates('date', 'month', order='DESC')
archives = {}
for i in arch:
tp = i.timetuple()
year = tp[0]
month = tp[1]
if year not in archives:
archives[year] = []
archives[year].append(month)
else:
if month not in archives[year]:
archives[year].append(month)
return render_to_response('blog/arhiva.html', {'archives':archives})
在我的模板中:
{% for years, months in archives.items %}
{{ years }}
{% for month in months %}
<a href="{{ years }}/{{ month }}">{{ month }}</a>
{% endfor %}
<br />
{% endfor %}
这返回的结果大概是:
2008 10
2009 10 9
2007 10
但是我完全无法对它们进行排序……无论是按年份还是其他方式,而且我也不知道怎么添加所有的月份(名称),我想要的格式是这样的:
2009 Ian Feb Mar Apr Mai Iun Iul Aug Sept Oct Noi Dec
2008 Ian Feb Mar Apr Mai Iun Iul Aug Sept Oct Noi Dec
2007 Ian Feb Mar Apr Mai Iun Iul Aug Sept Oct Noi Dec
有链接的月份是那些有文章的。
谢谢你的帮助!
附:抱歉我的英语不好。
补充:也许我问得不太清楚,我知道怎么获取日期,但我不知道怎么把它们格式化成这样的样子:
2009 Ian Feb Mar Apr Mai Iun Iul Aug Sept Oct Noi Dec
2008 Ian Feb Mar Apr Mai Iun Iul Aug Sept Oct Noi Dec
2007 Ian Feb Mar Apr Mai Iun Iul Aug Sept Oct Noi Dec
我从arch = Post.objects.dates('date', 'month', order='DESC')
中得到的结果是:
在模板中用{{ archives }}
显示的内容大概是:
[datetime.datetime(2009, 10, 1, 0, 0), datetime.datetime(2009, 9, 1, 0, 0),
datetime.datetime(2008, 10, 1, 0, 0), datetime.datetime(2007, 10, 1, 0, 0)]
然后我尝试了一个循环:
{% for archive in archives %}
{{ archive }} <br />
{% endfor %}
得到了:
2009-10-01 00:00:00
2009-09-01 00:00:00
2008-10-01 00:00:00
2007-10-01 00:00:00
之后我又尝试了这样的代码:
{% for archive in archives %}
{{ archive|date:"Y: m" }} <br />
{% endfor %}
结果是:
2009: 10
2009: 09
2008: 10
2007: 10
现在我卡住了,不知道怎么格式化数据,以便得到不同的年份和所有的月份,并且只有那些有文章的月份做成链接……
有什么想法吗?
提前谢谢你!
3 个回答
你可以考虑先从一个通用视图开始,然后在这个基础上进行扩展。
好的...所以对我来说,最终能正常工作的代码是:
在视图中:
rom_months = ['Ian', 'Feb', 'Mar', 'Apr', 'Mai', 'Iun',
'Iul', 'Aug', 'Sept', 'Oct', 'Noi', 'Dec']
def arhiva(request):
arch = Post.objects.dates('data', 'month', order='DESC')
archives = {}
for i in arch:
year = i.year
month = i.month
try:
archives[year][month-1][1] = True
except KeyError:
archives[year]=[[datetime.date(year,k+1,1),False,rom] for k, rom in enumerate(rom_months)]
archives[year][month-1][1] = True
return render_to_response('blog/arhiva.html', {'archives':sorted(archives.items(),reverse=True)})
在模板中:
{% for year, month_list in archives %}
{{ year }} Arhive:
{% for month, has_link, rom_month in month_list %}
{% if has_link %}<a href="/{{ month.year }}/{{ month.month }}/">{% endif %}
{{ rom_month }}
{% if has_link %}</a>{% endif %}
{% endfor %}
<br />
{% endfor %}
结果是:
2009 Arhive: Ian Feb Mar Apr Mai Iun Iul Aug Sept Oct Noi Dec
2008 Arhive: Ian Feb Mar Apr Mai Iun Iul Aug Sept Oct Noi Dec
2007 Arhive: Ian Feb Mar Apr Mai Iun Iul Aug Sept Oct Noi Dec
2003 Arhive: Ian Feb Mar Apr Mai Iun Iul Aug Sept Oct Noi Dec
再次非常感谢你的帮助。你真棒!我还是个新手! :)
首先,日期时间格式的字符串可以在Django文档中找到。我觉得你应该用大写的'M'而不是小写的。
因为你想显示一整年的12个月,即使只有部分月份有帖子,我们会创建一个archives
对象来传递给模板。我选择使用一个字典,其中
- 键是年份
- 值是一个包含12个
[datetime, bool]
对的列表,datetime
代表一个月份,bool
如果该月份有帖子则为True
。
下面是我们在视图中构建archives
对象的方法。
from datetime import date
def archive(request):
arch = Post.objects.dates('date', 'month', order='DESC')
archives = {}
for i in arch:
year = i.year
month = i.month
try:
archives[year][month-1][1]=True
except KeyError:
# catch the KeyError, and set up list for that year
archives[year]=[[date(y,m,1),False] for m in xrange(1,13)]
archives[year][month-1][1]=True
return render_to_response('blog/arhiva.html',
{'archives':sorted(archives.items(),reverse=True)})
在模板中,我们会遍历每年的月份,并在合适的时候显示链接。
{% for year, month_list in archives %}
{{ year }} archives:
{% for month, has_link in month_list %}
{% if has_link %}<a href="/{{ month.year }}/{{ month.month }}/">{% endif %}
{{ month|date:"M" }}
{% if has_link %}</a>{% endif %}
{% endfor %}
{% endfor %}
我没有检查所有的代码,所以可能会有一些小错误。最好使用url模板标签来处理链接,而不是直接写死网址格式。我觉得我的回答可能有点复杂,但我花了不少时间写这个,所以还是分享给大家吧。
国际化
我没有使用Django的国际化功能,所以无法帮你翻译。我建议你看看文档,如果有不明白的地方可以再问其他问题。
话虽如此,如果你只想用罗马尼亚语显示月份,这里有个不太优雅的方法。
首先,在视图的归档函数顶部添加以下一行。
rom_months = ['Ian', 'Feb', 'Mar', 'Apr', 'Mai', 'Iun',
'Iul', 'Aug', 'Sept', 'Oct', 'Noi', 'Dec']
然后在你的视图中替换以下一行
archives[year]=[[date(y,k+1,1),False,rom] for k, rom in enumerate(rom_months)]
最后在模板中替换以下内容
...
{% for month, has_link, rom_month in month_list %}
{% if has_link %}<a href="/{{ month.year }}/{{ month.month }}/">{% endif %}
{{ rom_month }}
...