编写视图函数
-
filter
就是过滤嘛,相当于 where了。 -
created_time__year
后面这是双下划线,表示 year 是created_time 的一个属性
blog/views.py
def archives(request, year, month):
post_list = Post.objects.filter(created_time__year=year,
created_time__month=month
).order_by('-created_time')
return render(request, 'blog/index.html', context={'post_list': post_list})
配置URL
正则表达式写路由地址时分组命名,分组匹配的结果就可以传导到视图函数中。
url(r'^archives/(?P[0-9]{4})/(?P[0-9]{1,2})/$', views.archive, name='archive'),
配置模板
官方文档 中提到,{% url 'blog:archive' date.year date.month %}
的做法是为去除模板中硬编码。archive 是 url 中的name,blog 是app名称。有了这两个指向,即便后面视图函数的名称发生变化,也不需要需改模板。——如果编程时长比较长的话,那么你肯定有较多修改函数名的经历。
遇到的问题:归档文章为空。
1. 查看orm 执行的sql。查询语句加 .query
就可以直接查看
post_list = Post.objects.filter(created_time__year=year,
created_time__month=month
).order_by('-created_time')
print(post_list.query)
打印出来的 sql 语句:
SELECT `blog_post`.`id`, `blog_post`.`title`, `blog_post`.`body`, `blog_post`.`created_time`,
`blog_post`.`modified_time`, `blog_post`.`excerpt`, `blog_post`.`category_id`, `blog_post`.`author_id`
FROM `blog_post` WHERE (EXTRACT(MONTH FROM CONVERT_TZ(`blog_post`.`created_time`,
'UTC', CST)) = 10 AND `blog_post`.`created_time` BETWEEN 2017-12-31 16:00:00 AND 2018-12-31
15:59:59.999999) ORDER BY `blog_post`.`created_time` DESC
2. convert_tz
convert_tz 是 Mysql 中用来转化时区的。把 UTC 时区转为当前时区:
select convert_tz(now(), "UTC", "GMT");
因为 settings.py
中写的 USE_TZ = True
,在这种情况下 Django 存入数据库的时间都是 UTC 时间,也就是会把我们本地时间减去 8 再存。这也是为什么打印出来的 Sql 里面会调用 convert_tz
。但是令我费解的是,一般 UTC 转化为本地时间,使用上面的sql 中的 GMT
就好了,不知道为啥 Django 用的CST
而且还没加引号... 这样的sql 根本无法直接执行的.....
3. extract
教程,http://www.w3school.com.cn/sql/func_extract.asp
extract
是用来日期中单独的部分,如年月日等,语法extract(unit from month)
。实例:
select extract(month from convert_tz(now(), "UTC", "GMT"))=10;
查看当前的月份是不是 10,如果等于10返回1,否则返回0.
这样就基本看懂了打印出来的sql了。
4 数据库中关于时区的设置
show variables like "%time_zone%";
显示:
Variable_name | Value |
+------------------+--------+
| system_time_zone | CST |
| time_zone | system |
time_zone 说明 mysql 使用是 system 的时区,system_time_zone 说明 system 使用的 CST 时区。CST:中国标准时间(China Standard Time)
5 修改时区
我看了些资料,上面建议直接把 mysql 的数据库设置为东八区比较好。于是设置:
vim /etc/mysql/mysql.cnf
[mysqld]
default-time-zone='+08:00'
重启数据库,/etc/init.d/mysql restart
, 查看了一下确实改了。
然后我在数据库里执行
select convert_tz(now(), "UTC", "GMT");
发现返回 null,于是发现需要设置一下,见教程
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root --force -p mysql
6 USE_TZ = False
我做了如上配置之后,但是还是选不出归档文章。看教程下面的评论设置 USE_TZ = False
,也就是不使用 UTC 时间,直接采用本地时间进行保存。这样虽然能选出归档文章了,但是数据前后就一致了,之前的文章是 UTC 格式的,但是现在存入文章都是本地时间。
而且 Django 文档中是不建议采用本地时间进行保存的。在我工作中,因为数据库保存的是本地时间,当程序国际化时保存本地时间就出现了问题。虽然这个博客走不到国际化的那一步,但是我觉得使用 UTC 存储时间还是有必要的。
不能执行的关键点是 CST,为什么 CST 不加引号,直接执行这个 sql