一.日期归档查询(知识点--个人站点页面的日期查询)
1 date_format
======================date,time,datetime===============
create table t_mul_new (d date,t time,dt datetime);
insert into t_mul values(now(),now(),now());
insert * from t_mul;
mysql > select * from t_mul;
mysql> use test2 Database changed mysql> mysql> create table t_mul_new(d date, t time, dt datetime); Query OK, 0 rows affected (2.11 sec) mysql> insert into t_mul_new values(now(), now(), now()); Query OK, 1 row affected, 1 warning (0.49 sec) mysql> select * from t_mul_new; +------------+----------+---------------------+ | d | t | dt | +------------+----------+---------------------+ | 2018-08-02 | 22:59:15 | 2018-08-02 22:59:15 | +------------+----------+---------------------+ 1 row in set (0.00 sec) mysql> select dt from t_mul_new; +---------------------+ | dt | +---------------------+ | 2018-08-02 22:59:15 | +---------------------+ 1 row in set (0.00 sec) mysql> select date_format(dt, "%Y-%m") from t_mul_new; +--------------------------+ | date_format(dt, "%Y-%m") | +--------------------------+ | 2018-08 | +--------------------------+ 1 row in set (0.05 sec) mysql> select date_format(dt, "%Y-%m-%d") from t_mul_new; +-----------------------------+ | date_format(dt, "%Y-%m-%d") | +-----------------------------+ | 2018-08-02 | +-----------------------------+ 1 row in set (0.00 sec) mysql> select date_format(dt, "%Y/%m/%d") from t_mul_new; +-----------------------------+ | date_format(dt, "%Y/%m/%d") | +-----------------------------+ | 2018/08/02 | +-----------------------------+ 1 row in set (0.00 sec) mysql>
2.extra
extra(select=None, where=None, params=None,
tables=None, order_by=None, select_params=None)
有些情况下,Django的查询语法难以简单的表达复杂的 WHERE 子句,对于这种情况, Django 提供了 extra() QuerySet修改机制 — 它能在 QuerySet生成的SQL从句中注入新子句
extra可以指定一个或多个 参数,例如 select, where or tables. 这些参数都不是必须的,但是你至少要使用一个!要注意这些额外的方式对不同的数据库引擎可能存在移植性问题.(因为你在显式的书写SQL语句),除非万不得已,尽量避免这样做
参数之select
The select 参数可以让你在 SELECT 从句中添加其他字段信息,它应该是一个字典,存放着属性名到 SQL 从句的映射。
queryResult=models.Article
.objects.extra(select={'is_recent': "create_time > '2017-09-05'"})
结果集中每个 Entry 对象都有一个额外的属性is_recent, 它是一个布尔值,表示 Article对象的create_time 是否晚于2017-09-05.
练习:
# in sqlite: article_obj=models.Article.objects
.filter(nid=1)
.extra(select={"standard_time":"strftime('%%Y-%%m-%%d',create_time)"})
.values("standard_time","nid","title") print(article_obj) # <QuerySet [{'title': 'MongoDb 入门教程', 'standard_time': '2017-09-03', 'nid': 1}]>
models.Article.objects(拿到所有的文章,等同于objects.all).extra(循环Article里边的每一个对象,给它加一个键值,键是“is_recent”,值是每一个Article对应执行的sql语句,写ORM的时候从来没这么写过,这个sql语句会对应每一个Article对象进行执行,执行一次统计出来一个结果如果大于了就返回1小于了就返回0;处理完的结果依然是Queryset,不同的是每一个Article对象多了个属性叫is_recent)
TruncMonth函数,例子:Sales商品表,按照之前就进行分组统计了,但它并没有,timestamp把它理解为create_time,TruncMonth把它截断只截到年月,然后赋值给了month字段;跟方式一是一样的,方式一用date_format来截断赋给了一个叫y_m_date这样子一个键。Sales里边就多加了一个叫month的属性。.values就相当于Group By month,再annotate统计哪个字段的数量,再最终显示month和c值。
二.个人站点信息的查询
views.py
def home_site(request, username, **kwargs): ''' 个人站点视图函数 :param request: :return: ''' print("username", username) user = UserInfo.objects.filter(username=username).first() # 过滤,判断是否有这个名字 # 判断当前用户是否存在! if not user: return render(request, "not_found.html") # 查询当前站点对象 blog = user.blog # 当前用户或者当前站点对应的所有文章 # 基于对象 # article_list = user.article_set.all() # 基于 __ article_list = models.Article.objects.filter(user=user) # 个人站点页面的标签与分类查询
# 每一个后的模型.objects.values("pk").annotate(聚合函数(关联表__统计字段)).values("表模型的所在字段")
# 查询每一个分类名称以及对应的文章数 ret = models.Category.objects.values("pk").annotate(c=Count("article__title")).values("title", "c") print(ret) # <QuerySet [{'c': 1, 'title': 'AI'}, {'c': 1, 'title': 'SQL'}, {'c': 1, 'title': 'JAVA'}]> # 查询当前站点的每一个分类名称以及对应的文章数 cate_list = models.Category.objects.filter(blog=blog).values("pk").annotate(c=Count("article__title")).values("title", "c") print(cate_list) # 查询当前站点的每一个标签名称以及对应的文章数 tag_list = models.Tag.objects.filter(blog=blog).values("pk").annotate(c=Count("article__title")).values("title", "c") print(tag_list) # 个人站点页面的日期查询 # 查询当前站点每一个年月的名称以及对应的文章数 # 新加一个字段的单表查询;你如果按create_time,它是年月日时分秒,根本没法分类分在一起
# 日期归档方式一: # date_list = models.Article.objects.filter(user=user).extra(select={"y_m_date": "date_format(create_time, '%%Y-%%m')"}).values("y_m_date").annotate(c=Count("title")).values("y_m_date", "c") # print(date_list) # 日期归档方式二:(导入TruncMonth函数) from django.db.models.functions import TruncMonth date_list = models.Article.objects.filter(user=user).annotate(month=TruncMonth("create_time")).values("month").annotate(c=Count("title")).values("month", "c") print(date_list) # 要把settings里边改成USE_TZ= False;不然会报错 return render(request, "home_site.html", {"username": username, "blog": blog, "article_list": article_list, "cate_list": cate_list, "tag_list": tag_list, "date_list": date_list})
在个人站点的视图函数中构建数据--->>传到home_site模板中进行渲染
三.个人站点页面的渲染布局
home_site.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/blog/bs/css/bootstrap.css"> <style> *{ margin: 0; padding: 0; } .header{ width: 100%; height: 60px; background-color: #369; } .content .title{ font-size: 18px; font-weight: 100; line-height: 60px; color: white; margin-left: 20px; } .backend{ float: right; color: white; text-decoration: none; font-size: 14px; margin-top: 10px; margin-right: 15px; } .pub_info{ margin-top: 10px; color: darkgrey; } </style> </head> <body> <div class="header"> <div class="content"> <p class="title"> <span>{{ blog.title }}</span> <a href="" class="backend">管理</a> </p> </div> </div> <div class="container"> <div class="row"> <div class="col-md-3"> <div class="panel panel-warning"> <div class="panel-heading">我的标签</div> <div class="panel-body"> {% for tag in tag_list %} <p><a href="">{{ tag.title }}</a>({{ tag.c }})</p> {% endfor %} </div> </div> <div class="panel panel-danger"> <div class="panel-heading">随笔分类</div> <div class="panel-body"> {% for cate in cate_list %} <p><a href="">{{ cate.title }}</a>({{ cate.c }})</p> {% endfor %} </div> </div> <div class="panel panel-info"> <div class="panel-heading">随笔归档</div> <div class="panel-body"> {% for date in date_list %} <p><a href="">{{ date.month|date:"Y-m" }}</a>({{ date.c }})</p> {% endfor %} </div> </div> </div> <div class="col-md-9"> <div class="article_list"> {% for article in article_list %} <div class="article_item clearfix"> {# clearfix:清除浮动 #} <h5><a href="">{{ article.title }}</a></h5> <div class="article_desc"> <span class="media-right"> {{ article.desc }} </span> </div> <div class="small pub_info pull-right"> <span>发布于  {{ article.create_time|date:"Y-m-d H:i" }}</span>   <span class="glyphicon glyphicon-comment"></span><a href="">评论({{ article.comment_count }})</a>   <span class="glyphicon glyphicon-thumbs-up"></span><a href="">点赞({{ article.up_count }})</a> </div> </div> <hr> {% endfor %} </div> </div> </div> </div> </body> </html>
views.py
from django.db.models.functions import TruncMonth date_list = models.Article.objects.filter(user=user).annotate(month=TruncMonth("create_time")).values("month").annotate(c=Count("title")).values("month", "c") print(date_list)
# 视图层要传 return render(request, "home_site.html", {"username": username, "blog": blog, "article_list": article_list, "cate_list": cate_list, "tag_list": tag_list, "date_list": date_list})
四.个人站点页面的跳转过滤功能的实现
url.py(路由设置)
# -*- encoding:utf-8 -*- urlpatterns = [ path('admin/', admin.site.urls), path('login/', views.login), path('index/', views.index), re_path('^$', views.index), # 在首页不用index也可以显示出 path('register/', views.register), path('get_valid_img/', views.get_valid_img), path('logout/', views.logout), # media配置 re_path(r"media/(?P<path>.*)$", serve, {"document_root": settings.MEDIA_ROOT}), # 个人站点url
re_path('^(?P<username>\w+)/$', views.home_site), # \w+:数字和字母 # 个人站点跳转(标签,分类,归档路由设计)
# 根路径直接加username,w+包含数字和字母,不包含特殊符号;有名分组;
# .* 传的时候让它能够识别出特殊符号 / ,任何符号都可以匹配的参数param组(如2019/02.html)
re_path('^(?P<username>\w+)/(?P<condition>tag|category|archive)/(?P<param>.*)/$', views.home_site), # \w+:数字和字母
]
views.py
def home_site(request, username, **kwargs): # 一个是接收2个参数,一个是接收4个参数;先接收2个,如果再有就放到**kwargs; ''' 个人站点视图函数 :param request: :return: ''' print("username", username) user = UserInfo.objects.filter(username=username).first() # 判断当前用户是否存在! if not user: return render(request, "not_found.html") # 查询当前站点对象 blog = user.blog # 当前用户或者当前站点对应的所有文章 # 基于对象 # article_list = user.article_set.all() # 基于 __ article_list = models.Article.objects.filter(user=user) if kwargs: condition = kwargs.get("condition") param = kwargs.get("param") if condition == "category": article_list = article_list.filter(category__title=param) elif condition == "tag": article_list = article_list.filter(tags__title=param) else: year, month = param.split("-") article_list = article_list.filter(create_time__year=year, create_time__month=month)
home_site.html
<div class="container"> <div class="row"> <div class="col-md-3"> <div class="panel panel-warning"> <div class="panel-heading">我的标签</div> <div class="panel-body"> {% for tag in tag_list %} <p><a href="/{{ username }}/tag/{{ tag.title }}">{{ tag.title }}</a>({{ tag.c }})</p> {% endfor %} </div> </div> <div class="panel panel-danger"> <div class="panel-heading">随笔分类</div> <div class="panel-body"> {% for cate in cate_list %} <p><a href="/{{ username }}/category/{{ cate.title }}">{{ cate.title }}</a>({{ cate.c }})</p> {% endfor %} </div> </div> <div class="panel panel-info"> <div class="panel-heading">随笔归档</div> <div class="panel-body"> {% for date in date_list %} <p><a href="/{{ username }}/archive/{{ date.month|date:"Y-m" }}">{{ date.month|date:"Y-m" }}</a>({{ date.c }})</p> {% endfor %} </div> </div> </div> <div class="col-md-9"> <div class="article_list"> {% for article in article_list %} <div class="article_item clearfix"> {# clearfix:清除浮动 #} <h5><a href="">{{ article.title }}</a></h5> <div class="article_desc"> <span class="media-right"> {{ article.desc }} </span> </div> <div class="small pub_info pull-right"> <span>发布于  {{ article.create_time|date:"Y-m-d H:i" }}</span>   <span class="glyphicon glyphicon-comment"></span><a href="">评论({{ article.comment_count }})</a>   <span class="glyphicon glyphicon-thumbs-up"></span><a href="">点赞({{ article.up_count }})</a> </div> </div> <hr> {% endfor %} </div> </div> </div> </div>