个人站点页面设计(ORM跨表与分组查询)
个人站点信息的查询
日期归档查询
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
views.py
def home_site(request, username): ''' 个人站点视图 :param request: :param username: :return: ''' print("username", username) user = UserInfo.objects.filter(username = username).first() #过滤 #判断用户是否存在 if not user: return render(request, "not_found.html") #查询当前站点对象 blog = user.blog #当前用户或者当前站点对应所有文章 #基于对象查询 #articile_list = user.article_set.all() #基于__ articile_list = models.Article.objects.filter(user=user) #user_id #每一个后的模型.objects.values("pk").annotate(聚合函数(关联表__统计字段)).values("表模型的所在字段") #查询每一个分类名称以及对应的文章数 ret = models.Category.objects.values("pk").annotate(c = Count("article__title")).values("title", "c") print(ret) #<QuerySet [{'title': 'egon的web', 'c': 2}, {'title': 'egon的sql', 'c': 1}, {'title': 'alex的微信小程序', 'c': 1}]> #查询当前站点的每一个分类名称以及对应的文章数 cate_list = models.Category.objects.filter(blog=blog).annotate(c = Count("article__title")).values_list("title", "c") #values是存元组.values("title", "c"),values_list是存字典 print(cate_list) #<QuerySet [{'title': 'egon的web', 'c': 2}, {'title': 'egon的sql', 'c': 1}]> #查询当前站点的每一个标签名称以及对应文章数 .annotate(Count("article__name")) 反向查询 tag_list = models.Tag.objects.filter(blog=blog).values("pk").annotate(c = Count("article")).values_list("title","c") #每个标签自己的名字以及统计出来的文章数 print(tag_list) #<QuerySet [('web', 3), ('数据库', 1), ('服务器', 1)]>; #查询当前站点每一个年月的名称以及对应的文章数 (新加一个字段的单表查询) #ret = models.Article.objects.extra(select={"is_recent": "create_time > '2018-09-05'"}).values("title", "is_recent") #print(ret) #<QuerySet [{'is_recent': 0, 'title': '猫眼电影App抓包获取评论数据接口'}, {'is_recent': 0, 'title': 'RESTful源码笔记之RESTful Framework的Mixins小结'}, {'is_recent': 0, 'title': '微信小程序开发04-打造自己的UI库'}, {'is_recent': 0, 'title': 'redis系列--主从复制以及redis复制演进'}]> #ret = models.Article.objects.extra(select={"y_m_d_date": "date_format(create_time,'%%Y-%%m-%%d')"}).values("title","y_m_d_date") #print(ret)#<QuerySet [{'y_m_d_date': '2018-08-01', 'title': '猫眼电影App抓包获取评论数据接口'}, {'y_m_d_date': '2018-08-01', 'title': 'RESTful源码笔记之RESTful Framework的Mixins小结'}, {'y_m_d_date': '2018-08-01', 'title': '微信小程序开发04-打造自己的UI库'}, {'y_m_d_date': '2018-08-02', 'title': 'redis系列--主从复制以及redis复制演进'}]> #方式一 date_list = models.Article.objects.filter(user=user).extra(select={"y_m_date": "date_format(create_time,'%%Y-%%m-%%d')"}).values("y_m_date").annotate(c=Count("nid")).values("y_m_date","c") print(date_list) #<QuerySet [{'y_m_date': '2018-08-01', 'c': 2}, {'y_m_date': '2018-08-02', 'c': 1}]> #方式二 from django.db.models.functions import TruncMonth ret = models.Article.objects.filter(user=user).annotate(month = TruncMonth("create_time")).values("month").annotate(c=Count("nid")).values_list("month","c") print("ret---->", ret) #ret----> <QuerySet [(datetime.datetime(2018, 8, 1, 0, 0), 3)]> 要把settings里边改成USE_TZ = False;不然会报错 return render(request, "home_site.html")
个人站点页面的渲染布局
home_site.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> *{ margin:0; padding:0; } .header{ width:100%; height: 60px; background-color: #369; } .header .title{ font-size: 18px; font-weight: 100; line-height: 60px; color: white; margin-left: 15px; margin-top: -10px;; } .backend{ float:right; color: white; text-decoration: none; font-size: 16px; margin-right:10px; margin-top: 10px;; } .pub_info{ margin-top: 10px; color: darkgrey; } </style> <link rel="stylesheet" href="/static/blog/bootstrap/css/bootstrap.css"> </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>{{ tag.0 }}({{ tag.1 }})</p> {% endfor %} </div> </div> <div class="panel panel-danger"> <div class="panel-heading">随笔分类</div> <div class="panel-body"> {% for cate in cate_list %} <p>{{ cate.0 }}({{ cate.1 }})</p> {% endfor %} </div> </div> <div class="panel panel-success"> <div class="panel-heading">随笔归档</div> <div class="panel-body"> {% for date in date_list %} <p>{{ date.0 }}({{ date.1 }})</p> {% endfor %} </div> </div> </div> <div class="col-md-9"> <div class="article_list"> {% for article in article_list %} <div class="article-item clearfix"> <h5><a href="">{{ article.title }}</a> </h5> <div class="article-desc"> {{ article.desc }} </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>评论({{ article.comment_count }}) <span class="glyphicon glyphicon-thumbs-up"></span>点赞({{ article.up_count }}) </div> </div> <hr> {% endfor %} </div> </div> </div> </div> </body> </html>
views.py
#方式一 #date_list = models.Article.objects.filter(user=user).extra(select={"y_m_date": "date_format(create_time,'%%Y-%%m-%%d')"}).values("y_m_date").annotate(c=Count("nid")).values("y_m_date","c") date_list = models.Article.objects.filter(user=user).extra(select={"y_m_date": "date_format(create_time,'%%Y-%%m-%%d')"}).values("y_m_date").annotate(c=Count("nid")).values_list("y_m_date","c") #取字典必须按照字典的取法进行渲染 print(date_list) #<QuerySet [{'y_m_date': '2018-08-01', 'c': 2}, {'y_m_date': '2018-08-02', 'c': 1}]> return render(request, "home_site.html", {"blog": blog,"article_list":article_list,
"cate_list": cate_list, "tag_list": tag_list, "date_list": date_list}) #视图层要传
个人站点页面的跳转过滤功能的实现
urls.py
urlpatterns = [ path('admin/', admin.site.urls), path('login/',views.login), path('index/',views.index), path('logout/', views.logout), re_path('^$',views.index), #在首页不用index也可以显示出 path('get_validCode_img/',views.get_validCode_img), path('register/',views.register), #media配置 re_path(r"media/(?P<path>.*)$", serve, {"document_root":settings.MEDIA_ROOT}), #个人站点的跳转 re_path('^(?P<username>\w+)/(?P<condition>tag|category|archive)/(?P<param>.*)/$', views.home_site), #home_site(request,username="egon",condition="tag",param="python") #路由设置 #个人站点url re_path('^(?P<username>\w+)$', views.home_site), #home_site(request,username="egon") 上边home_site要接收4个参数,匹配到它的接收2个参数 ]
views.py
def home_site(request, username, **kwargs): ''' 个人站点视图 :param request: :param username: :return: ''' print("kwargs", kwargs) #kwargs {'condition': 'tag', 'param': 'web'} print("username", username) #username egon user = UserInfo.objects.filter(username = username).first() #过滤 #判断用户是否存在 if not user: return render(request, "not_found.html") #查询当前站点对象 blog = user.blog #当前用户或者当前站点对应所有文章 #基于对象查询 #articile_list = user.article_set.all() #基于__ if kwargs: condition = kwargs.get("condition") param = kwargs.get("param") #2012-12 if condition == "category": #http://127.0.0.1:8000/egon/category/egon的web/ article_list = models.Article.objects.filter(user=user).filter(category__title=param) elif condition == "tag": #http://127.0.0.1:8000/egon/tag/web/ article_list = models.Article.objects.filter(user=user).filter(tags__title=param) else: year, month = param.split("-") #http://127.0.0.1:8000/egon/archive/2018-07/ article_list = models.Article.objects.filter(user=user).filter(create_time__year=year, create_time__month=month) else: #如果没值就走个人站点 article_list = models.Article.objects.filter(user=user) #user_id
优化下
实现点击跳转功能
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.0 }}">{{ tag.0 }}({{ tag.1 }})</a></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.0 }}"> {{ cate.0 }}({{ cate.1 }})</a></p> {% endfor %} </div> </div> <div class="panel panel-success"> <div class="panel-heading">随笔归档</div> <div class="panel-body"> {% for date in date_list %} <p><a href="/{{ username }}/archive/{{ date.0 }}"> {{ date.0 }}({{ date.1 }})</a></p> {% endfor %} </div> </div> </div> <div class="col-md-9"> <div class="article_list"> {% for article in article_list %} <div class="article-item clearfix"> <h5><a href="">{{ article.title }}</a> </h5> <div class="article-desc"> {{ article.desc }} </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>评论({{ article.comment_count }}) <span class="glyphicon glyphicon-thumbs-up"></span>点赞({{ article.up_count }}) </div> </div> <hr> {% endfor %} </div> </div> </div> </div>