项目内容
在Django基础项目(ToDoList)的基础上完成以下功能:
1、实现一个中间件,该中间件可以检测到用户浏览器版本信息,如果用户使用的浏览器低于IE9则显示用户升级浏览器的页面,否则不能访问和使用到ToDoList的功能
2、在添加的待办事项里面增加一个发布时间,设计一个过滤器,可以格式化时间显示效果。(显示成发布于1小时前,1天前,1周前,1月前,1年前这样的效果。)
参考文档
具体实现
定义一个判断用户源的中间件
这里定义了一个判断用户源的中间件【middleware.py】,这里有一个小bug:判断来源可以不全
from django.http import HttpResponse
class CheckSoureMiddware(object):
def process_request(self, request):
from_source = request.META['HTTP_USER_AGENT']
print('from_source ', from_source)
if 'MSIE 6.0' in from_source:
request.session['from_source'] = 'MSIE 6.0'
return HttpResponse('''<div align="center"><img src="../static/img/old.png" class="alignleft" alt="升级浏览器"/></div>''')
if 'Trident/7.0' in from_source:
request.session['from_source'] = 'MSIE 7.0'
return HttpResponse('''<div align="center"><img src="../static/img/old.png" class="alignleft" alt="升级浏览器"/></div>''')
if 'Trident/7.0' in from_source:
request.session['from_source'] = 'MSIE 8.0'
return HttpResponse('''<div align="center"><img src="../static/img/old.png" class="alignleft" alt="升级浏览器"/></div>''')
else:
request.session['from_source'] = 'pc'
将中间件注册
MIDDLEWARE_CLASSES = [
'todolist.middleware.CheckSoureMiddware',
]
定义一个格式化时间的过滤器
修改数据库相关字段
修改储存时间字段【models.py】
from django.db import models
import django.utils.timezone as timezone
# Create your models here.
class Todolist(models.Model):
add_date = models.DateTimeField()
同步更新数据库【manage.py】
(env_py35_django) D:\MaiZi_Edu\Dropbox\Maizi\Django_up\django_homework_end>python manage.py makemigrations
Migrations for 'todolist':
0003_todolist_add_date.py:
- Add field add_date to todolist
(env_py35_django) D:\MaiZi_Edu\Dropbox\Maizi\Django_up\django_homework_end>python manage.py migrate
Operations to perform:
Apply all migrations: sessions, admin, contenttypes, todolist, auth
Running migrations:
Rendering model states... DONE
Applying todolist.0003_todolist_add_date... OK
修改html文件,加入时间显示【todolist.html】
<div class="text_holder">
{{ todolist_list.body }} --- {{todolist_list.add_date }}
<div class="btn-group pull-right">
<button class="delete btn btn-warning" data-id="{{ todolist_list.id }}">Delete</button>
<button class="edit btn btn-success" data-id="{{ todolist_list.id }}">Edit</button>
</div>
</div>
创建poll_filter.py文件并使用
使用if和else实现【poll_filter_old.py】
# coding: utf-8
# author: spareribs
from django import template
import time
import datetime
from dateutil.relativedelta import relativedelta
register = template.Library()
# 将 datetime obj 转换成 timestamp
def date_to_timestamp(date_time):
return time.mktime(date_time.timetuple())
def time_before():
timestamp_before = {
# 1分钟前的时间戳
'a_minute_before': '',
# 1小时前的时间戳
'a_hour_before': '',
# 1天前的时间戳
'a_day_before': '',
# 1周前的时间戳
'a_week_before': '',
# 1个月的时间戳
'a_month_before': '',
# 1年的时间戳
'a_year_before': '',
}
# 获取当前时间
now = datetime.datetime.now()
# 得到1个分钟前的时间(datetim obj)
timestamp_before['a_minute_before'] = now + relativedelta(minutes=-1)
# 得到1个小时前的时间(datetim obj)
timestamp_before['a_hour_before'] = now + relativedelta(hours=-1)
# 得到1天前的时间(datetim obj)
timestamp_before['a_day_before'] = now + relativedelta(days=-1)
# 得到1周前的时间(datetim obj)
timestamp_before['a_week_before'] = now + relativedelta(weeks=-1)
# 得到1个月前的时间(datetim obj)
timestamp_before['a_month_before'] = now + relativedelta(months=-1)
# 得到1年前的时间(datetim obj)
timestamp_before['a_year_before'] = now + relativedelta(years=-1)
# 将datetim obj转换成 timestamp
for time_tag in timestamp_before:
timestamp_before[time_tag] = date_to_timestamp(timestamp_before[time_tag])
return timestamp_before
@register.filter()
def format_date(value):
before = time_before()
add_date = date_to_timestamp(value)
if before['a_minute_before'] < add_date:
print(before['a_minute_before'], add_date)
time_ = int(61 - (add_date - before['a_minute_before']))
return "{0}秒前发布".format(time_)
elif before['a_hour_before'] < add_date:
print(before['a_hour_before'], add_date)
time_ = int(61 - (add_date - before['a_hour_before']) / 60)
return "{0}分钟前发布".format(time_)
elif before['a_day_before'] < add_date:
print(before['a_day_before'], add_date)
time_ = int(25 - (add_date - before['a_day_before']) / 3600)
return "{0}小时前发布".format(time_)
elif before['a_week_before'] < add_date:
print(before['a_week_before'], add_date)
time_ = int(8 - (add_date - before['a_week_before']) / 86400)
return "{0}天前发布".format(time_)
elif before['a_month_before'] < add_date:
print(before['a_month_before'], add_date, before['a_month_before'])
time_ = int(5 - (add_date - before['a_month_before']) / 604800)
return "{0}周前发布".format(time_)
elif before['a_year_before'] < add_date:
print(before['a_year_before'], add_date)
time_ = int(13 - (add_date - before['a_year_before']) / 2592000)
return "{0}个月前发布".format(time_)
else:
print(before, add_date)
return "1年前发布"
更简单的方法实现【poll_filter.py】
# coding: utf-8
# author: spareribs
from django import template
import datetime
register = template.Library()
@register.filter()
def time_before(d):
chunks = (
(60 * 60 * 24 * 365, u'年'),
(60 * 60 * 24 * 30, u'月'),
(60 * 60 * 24 * 7, u'周'),
(60 * 60 * 24, u'天'),
(60 * 60, u'小时'),
(60, u'分钟'),
(1, u'秒'),
)
# 如果不是datetime类型转换后与datetime比较
if not isinstance(d, datetime.datetime):
d = datetime.datetime(d.year, d.month, d.day)
now = datetime.datetime.now()
delta = now - d
print(delta)
# 忽略毫秒
before = delta.days * 24 * 60 * 60 + delta.seconds
# 刚刚过去的1分钟
if before <= 3:
return u'刚刚'
for seconds, unit in chunks:
count = before // seconds
if count != 0:
break
return str(count) + str(unit) + u"前发布"
修改前端,格式化时间
主要的内容如下【todolist.html】
{% load poll_filter %}
{{ todolist_list.body }} --- {{ todolist_list.add_date | time_before }}
遇到的问题
遇到数据库存储时间对应不上的问题
修改了配置文件这两个参数
# TIME_ZONE = 'UTC'
TIME_ZONE = 'Asia/Shanghai'
# USE_TZ = True
USE_TZ = False
中间件HttpResponse问题
本来想在中间件加个重定向的HttpResponseRedirect,发现不能用。
HttpResponse不会再执行其他任何中间件
其实这个应该在前端使用js来判断更为合适