整体设计思路
1. 应该包含的内容:应该包含标签,随笔,档案三个类别2. 处理请求的逻辑:一般由URL匹配路径,views负责数据处理以及表查询,最后由render渲染指定页面,如果有表查询,则数据也通过runder传递,并且由模板标签显示3. 数据查询的方式1. 第一个查询的目标:所有的[标题,category分类下有多少篇文章];2.4. 日期归档查询1. date_format==============date, time, datetime======================create table t_mul(d, date, t time, dt datetime);insert into t_mul values(now(), now(), now());select * form t_mul;mysql>select * from t_mul;+------------+------------+--------------------|| d + t | dt |+------------+------------+--------------------|| 2017-08-01 | 19:42:22 | 2017-08-01 19:42:22|+------------+------------+--------------------|select date_format(dt, "%Y/%m%/d")from t_mul;5. extra参数说明extra(self, select=None, where=None, params=None, tables=None,order_by=None, select_params=None)功能描述"""Add extra SQL fragments to the query."""ret = models.Category.objects.extra(select={'is_recent':"create_time > '2021-08-25'"})描述: 结果集中每个Entry对象的都有一个额外的属性```is_recent```, 它是一个布尔值,表示Article的对象create_time 是否晚于20210906
辅助性知识增加
数据库日期查询
mysql> select action_time from django_admin_log;+----------------------------+| action_time |+----------------------------+| 2021-09-03 04:44:22.186919 || 2021-09-03 04:49:20.520822 || 2021-09-03 07:12:52.348922 || 2021-09-03 07:13:38.546223 || 2021-09-03 07:13:58.242131 || 2021-09-03 07:14:15.347263 || 2021-09-03 07:16:10.456608 || 2021-09-03 07:16:16.506109 || 2021-09-03 07:17:54.765210 || 2021-09-03 07:18:01.567483 || 2021-09-03 07:18:46.797706 || 2021-09-03 07:19:14.759294 || 2021-09-03 07:21:18.118932 || 2021-09-03 07:21:20.760727 || 2021-09-03 13:22:46.382014 || 2021-09-03 13:22:58.575269 || 2021-09-05 14:56:17.859757 || 2021-09-05 14:56:27.985515 || 2021-09-05 14:56:39.436340 |+----------------------------+19 rows in set (0.00 sec)mysql> select date_format(action_time,"%Y-%m-%d") from django_admin_log;+-------------------------------------+| date_format(action_time,"%Y-%m-%d") |+-------------------------------------+| 2021-09-03 || 2021-09-03 || 2021-09-03 || 2021-09-03 || 2021-09-03 || 2021-09-03 || 2021-09-03 || 2021-09-03 || 2021-09-03 || 2021-09-03 || 2021-09-03 || 2021-09-03 || 2021-09-03 || 2021-09-03 || 2021-09-03 || 2021-09-03 || 2021-09-05 || 2021-09-05 || 2021-09-05 |+-------------------------------------+19 rows in set (0.00 sec)mysql> select date_format(action_time,"%Y/%m/%d") from django_admin_log;+-------------------------------------+| date_format(action_time,"%Y/%m/%d") |+-------------------------------------+| 2021/09/03 || 2021/09/03 || 2021/09/03 || 2021/09/03 || 2021/09/03 || 2021/09/03 || 2021/09/03 || 2021/09/03 || 2021/09/03 || 2021/09/03 || 2021/09/03 || 2021/09/03 || 2021/09/03 || 2021/09/03 || 2021/09/03 || 2021/09/03 || 2021/09/05 || 2021/09/05 || 2021/09/05 |+-------------------------------------+19 rows in set (0.00 sec)mysql>
终端操作数据查询的必备数据
>>> from blog.models import *>>> from django.db.models import Count>>> user = UserInfo.objects.first()>>> user<UserInfo: developer>>>> blog = user.blog>>> blog<Blog: Yuan的个人博客>
第一个设计—制作IP加username的快捷访问方式
urls.py[36] & views.py
"""whereabouts URL ConfigurationThe `urlpatterns` list routes URLs to views. For more information please see:https://docs.djangoproject.com/en/3.2/topics/http/urls/Examples:Function views1. Add an import: from my_app import views2. Add a URL to urlpatterns: path('', views.home, name='home')Class-based views1. Add an import: from other_app.views import Home2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')Including another URLconf1. Import the include() function: from django.urls import include, path2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))"""from django.contrib import adminfrom django.urls import path, include, re_pathfrom django.conf import settingsfrom django.conf.urls.static import staticfrom blog import viewsurlpatterns = [path('admin/', admin.site.urls),path('summernote/', include('django_summernote.urls')),# http://127.0.0.1:8001/login/path('login/', views.login),# http://127.0.0.1:8001/logout/path('logout/', views.logout),path('get_validCode_img/', views.get_validCode_img),# http://127.0.0.1:8001/index/path('index/', views.index),# http://127.0.0.1:8001/re_path('^$', views.index),# http://127.0.0.1:8001/registry/path('registry/', views.registry),# 个人站点URLre_path('^(?P<username>\w+)$', views.home_site),]if settings.DEBUG:urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)#########################################################################################def home_site(request, username):"""个人站点视图函数"""print("username", username)return render(request, "blog/home_site.html")
被渲染网页home_site.html
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>个人站点表</title></head><body></body></html>
实现效果

第二个设计—过滤用户,若不存在则返回404
views.py
def home_site(request, username):"""个人站点视图函数"""print("username", username)ret=UserInfo.objects.filter(username=username).exists()# 判断用户是否存在if not ret:return render(request, "blog/not_found.html")#return render(request, "blog/home_site.html")
home_site.html
<!DOCTYPE html>{% load static %}<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="stylesheet" href="{% static 'static/blog/css/home_site_self.css' %}"><title>404 - 页面丢失啦</title></head><body><div class="main-container"><img class="img-container container-item"><img src="{% static 'static/blog/img/profile.png' %}" style="width: 40vw;position: fixed;left: 50%;top: 50%;transform: translate(-50%,-50%);"></img><div class="text-container container-item"><div class="code">404</div><div class="msg">你查看的页面貌似丢失了呢...</div><div class="action">请确认您输入的网址正确,若问题持续存在,请发送邮件至 419997284@qq.com,与CaesarTylor联系</div><div class="action"><p><a href="/">返回网站首页</a></p></div></div></div></body></html>
home_site_self.css
* {padding: 0;margin: 0;}html {height: 100%;}/*#E71D36#FF9F1C*/body {background: #FF9F1C;animation: bodyAction 2s ease-in-out;}@keyframes bodyAction {0% {background: #E71D36;}100% {background: #FF9F1C ;}}.num {font-size: 200px;position: fixed;color: #FF9F1C;text-shadow: 5px 0 0 #000;}.num span {display: block;vertical-align: top;height: 200px;width: 180px;text-align: center;line-height: 200px;}.num .check {color: #E71D36;}@keyframes checkAction {0% {color: #FF9F1C;}100% {color: #E71D36;}}.num.num1 {top: -1600px;left: calc(50% - 400px);animation: num1Action 2s ease-in-out;}@keyframes num1Action {0% {top: 0px;}100% {top: -1600px;/* color: #E71D36; */}}.num.num2 {left: calc(50% - 200px);top: -1200px;animation: num2Actoin 2s ease-in-out;}@keyframes num2Actoin {0% {top: 0px;}100% {top: -1200px;/* color: #E71D36; */}}.num.num3 {left: calc(50% + 0px);top: -1600px;animation: num3Actoin 2s ease-in-out;}@keyframes num3Actoin {0% {top: 0px;}100% {top: -1600px;/* color: #E71D36; */}}.num.num4 {left: calc(50% + 200px);top: -1200px;animation: num4Actoin 2s ease-in-out;}@keyframes num4Actoin {0% {top: 0px;}100% {top: -1200px;/* color: #E71D36; */}}
最终效果

问题记录
Cannot resolve keyword 'article' into field. Choices are: Article_category, blog, blog_id, nid, title
关联代码
ret=models.Category.objects.values("pk").annotate(c=Count("article__title")).values("title","c")
知识点—聚合查询
https://docs.djangoproject.com/zh-hans/3.2/topics/db/aggregation/
第三个设计—-如何添加Tag标签
第一种在数据库中插入

第二种后台管理页面添加[面向对象]

数据库关系说明
1. 左侧第一栏是自动排序,第二栏是用户创建的title, 第三栏则是绑定用户ID,此ID来自于UserInfo中nid2. 在后台添加时则需要选择对应的个人站点,也就相当于第三列中blog的标记


第四个设计:从数据库查询数据
整体设计思路
1. 需要查询的数据:当前用户或者当前站点对应的所有文章查询每一个分类名称以及对应的文章数查询当前站点的每一个分类名称以及对应的文章数目查询当前站点的每一个标签名称以及对应的文章数2. 查询的路径以及优缺点分析1. Python console 查询,优点:无需频繁切换浏览器与控制台输出,几乎不需要等待;缺点:变量命令麻烦,需要导入包;数据更新需要退出再重新进入;每次进出数据不能保存;2. IDE + browser 查询,优点:可视化,美观;数据库迁移与数据查询分开,前者不影响数据显示;变量和导包报错可以保存为固定代码,无需重复敲代码;3. 细节处理1. 查询的时候应该仔细检查该表下有那些字段,避免字段错误造成重复报错;db_column会修改列名,因此需要注意字段名是否正确;2. tag与article之间毫无关系,连路人都算不上,但是他们通过blog_id联系起来,一个人发表多篇文章,它又希望给文章绑定tag标签,但是由于两表完全没有关系,那么就建立一个中间表,专门用来绑定tag与article的关系;3. 对抽取数据的表达选择上,使用list类型的原因是;在展示数据时,可以用索引分开一个变量传递过来的数据,实现对数据的分类;4. 可扩展性与数据隔离1. 为了实现原地跳转展示信息,URL部分用condition和param做数据分流,此处留有扩展性,还可以做多个下拉菜单一样的两级内容展示;2. 用于数据查询中的条件匹配的两个变量,如何隔离存储;3. 前端展示中,预期后期会为多个H5文件制作模板,然后以模板标签嵌入多个实例中;H5中的Bootstrap语法部分[panel]可以重用,代码重构;
查询标签Tag以及对应的文章数
# 能够查出数据的查询语句tags = models.Tag.objects.values('pk').annotate(c=Count("blog_id")).values("title", "c").filter(blog_id=blog)标签名称以及对应的文章数<QuerySet [{'title': 'DS', 'c': 1}, {'title': '服务器', 'c': 1}]># 不进行过滤tags = models.Tag.objects.values('pk').annotate(c=Count("blog_id")).values("title", "c")标签名称以及对应的文章数<QuerySet [{'title': '前端', 'c': 1}, {'title': 'DS', 'c': 1}, {'title': '软件工程', 'c': 1}, {'title': '数据库', 'c': 1}, {'title': '服务器', 'c': 1}]># 能拿到数据的查询方法tags = models.Tag.objects.values('pk').annotate(c=Count("article")).values("title", "c").exclude(blog_id = nid)<QuerySet [{'title': '前端', 'c': 1}, {'title': '软件工程', 'c': 1}]>标签名称以及对应的文章数<QuerySet [{'title': '前端', 'c': 1}, {'title': '软件工程', 'c': 1}, {'title': '数据库', 'c': 0}]># 最终的匹配语句 用tag中的blog_id与用户的blog_id做匹配,后者要先从userinfo表中取得tags = models.Tag.objects.values('pk').annotate(c=Count("article")).values("title", "c").filter(blog_id=nid)<QuerySet [{'title': '前端', 'c': 1}, {'title': '软件工程', 'c': 1}]>标签名称以及对应的文章数<QuerySet [{'title': 'DS', 'c': 2}, {'title': '服务器', 'c': 0}]> # 用户Alex的数据
查询当前站点每一个年月的名称以及对应的文章数—-单表分组查询
日期过滤语句的演练
mysql> select date_format(create_time,"%Y/%m/%d") from 文章表;+-------------------------------------+| date_format(create_time,"%Y/%m/%d") |+-------------------------------------+| 2021/09/03 || 2021/09/03 || 2021/09/03 || 2021/09/07 |+-------------------------------------+
逐步求解
# 在django的查询语句中引入SQL语句,且查询结果用0/1标注,而非只显示目标内容era = models.Article.objects.extra(select={"is_recent":"create_time > '2021-09-07'"}).values("title", "is_recent")print(era)<QuerySet [{'is_recent': 0, 'title': 'spring 快速入门'}, {'is_recent': 0, 'title': '数据结构与算法——查找算法-斐波那契(黄金分割法)查找'}, {'is_recent': 0, 'title': '5M1E,软件质量管理最佳解决方案'}, {'is_recent': 1, 'title': 'LeetCode通关:通过排序一次秒杀五道题,舒服!'}]>era_a = models.Article.objects.extra(select={"y_m_d_date":"date_format(create_time,'%%Y-%%m-%%d')"}).values('title', 'y_m_d_date')<QuerySet [{'y_m_d_date': '2021-09-03', 'title': 'spring 快速入门'}, {'y_m_d_date': '2021-09-03', 'title': '数据结构与算法——查找算法-斐波那契(黄金分割法)查找'}, {'y_m_d_date': '2021-09-03', 'title': '5M1E,软件质量管理最佳解决方案'}, {'y_m_d_date': '2021-09-07', 'title': 'LeetCode通关:通过排序一次秒杀五道题,舒服!'}]># 注意时间过滤规则的书写,可类比sqlite语法era_a = models.Article.objects.extra(select={"y_m_d_date": "date_format(create_time,'%%Y-%%m-%%d')"}).values( 'title', 'y_m_d_date')<QuerySet [{'y_m_d_date': '2021-09-03', 'title': 'spring 快速入门'}, {'y_m_d_date': '2021-09-03', 'title': '数据结构与算法——查找算法-斐波那契(黄金分割法)查找'}, {'y_m_d_date': '2021-09-03', 'title': '5M1E,软件质量管理最佳解决方案'}, {'y_m_d_date': '2021-09-07', 'title': 'LeetCode通关:通过排序一次秒杀五道题,舒服!'}]># 用article中的user与userinfo中的nid做匹配,用于过滤不属于当前对象的文章era_b = models.Article.objects.filter(user=nid).extra(select={"y_m_date": "date_format(create_time,'%%Y-%%m')"}).values( 'y_m_date').annotate(c=Count("nid")).values('y_m_date', 'c')<QuerySet [{'y_m_date': '2021-09-03', 'c': 1}, {'y_m_date': '2021-09-07', 'c': 1}]>
第五个设计:个人站点页面样式设计
head设计
源码
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>个人站点表</title><style>*{margin:0;padding:0;}.header{width: 100%;height:60px;background-color: #d3dce6;}.header .title{font-size:18px;font-weight:100;line-height:60px; /*设置上下居中*/color:lightpink;margin-left: 14px;margin-top: -10px;}.backend{float:right;color:darkslategrey;text-decoration: none; /*去掉多余的下划线*/font-size:16px;margin-left: 10px;margin-top: 10px; /*文字下移*/}</style></head><body><div class="header"><div class="content"><p class="title"><span>{{ blog.title }}</span><a href="" class="backend">管理</a></p></div></div></body></html>
效果

文章表的渲染
源码
<div class="container"><div class="row"><div class="col-md-3"></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>
效果

标签,随笔分类,随笔归档的渲染
源码
<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 ym in year_month %}<p>{{ ym.0 }}({{ ym.1 }})</p>{% endfor %}</div></div></div>
效果

原地跳转访问指定分类或者标签下的所有文章表
处理逻辑以及数据提取和处理
2. 数据处理过程1. 需要查找两类信息,分别根据category & tag找到该用户下的所有文章;2. condition交给if 条件语句,专心处理param参数与文章表进行匹配的问题;3. param传递的参数是category下的title,由可视化窗口可以观察得到;只能将传递 参数param与title进行匹配;4. 其次则为筛选用户:category中有blog参数,绑定的值为blog.id,blog.nid在用户表中与用户是一对一的关系;还需要确认category与user.id之间的关系;5. 首先blog为个人站点,user与其为一对一关系,然后通过blog与category & tag产生依赖关系;6. 匹配规则: 第一层判断,如果拿到数据,condition & param就进行匹配,如果没有拿到数据,那么就筛选当前用户的所有文章;第二层逻辑:在拿到数据的情况下,对condition中的category和param进行分流,前者从数据库抽取当前用户的blog,blog下的category,然后输出category下的所有文章,后者则获取blog,blog下的tag,输出tag下的所有文章;3. 修正category & tag都与blog_nid关联,但是字段名不一样,遂做统一,将tag绑定的blog改为b
源码
# URL# 个人站点的原地跳转[点击标签触发内容]re_path('^(?P<username>\w+)/(?P<condition>tag|category|archive)/(?P<param>.*)/$', views.home_site),# 查询当前站点对象以及idblog = user.bloguserid = user.nidnid = blog.nid # 用作原地跳转标签匹配# 当前用户或者当前站点对应的所有文章if kwargs:condition = kwargs.get("condition")param = kwargs.get("param")if condition == "category":article_list = models.Article.objects.filter(category__blog=nid).filter(category__title__icontains=param)elif condition == 'tag': # 通过tags字段回到Tagarticle_list = models.Article.objects.filter(tags__blog_id=nid).filter(tags__title__icontains=param)else: # filter(user=nid)以当前用户的ID筛选所有文章article_list = models.Article.objects.filter(user=userid) # 抽取当前用户站点下的所有文章
效果
该效果由后期编写测试样例提供,此刻不再展示
代码优化
V1
"""个人站点视图函数"""print("kwargs", kwargs)print("username",username)# 查询当前站点对象以及idblog = user.bloguserid = user.nidnid = blog.nid # 用作原地跳转标签匹配# 当前用户或者当前站点对应的所有文章if kwargs:condition = kwargs.get("condition")param = kwargs.get("param") # 2012-12if condition == "category":article_list = models.Article.objects.filter(category__blog=nid).filter(category__title__icontains=param)elif condition == 'tag': # 通过tags字段回到Tagarticle_list = models.Article.objects.filter(tags__blog_id=nid).filter(tags__title__icontains=param)else:year, month = param.split("-")article_list = models.Article.objects.filter(category__blog=nid).filter(create_time__year=year,create_time__month=month)else:article_list = models.Article.objects.filter(user=userid) # 抽取当前用户站点下的所有文章# 查询当前站点的每一个分类名称以及对应的文章数目; 能用Article_category是因为article包含了外键categorycate_list = models.Category.objects.filter(blog__nid=nid).values_list("title").annotate(c=Count("Article_category"))# 查询当前站点的每一个标签名称以及对应的文章数tag_list = models.Tag.objects.values('pk').annotate(c=Count("article")).values_list("title", "c").filter(blog_id=nid)# 查询当前站点每一个年月的名称以及对应的文章数---单表分组查询# 引入函数专门处理日期分组:from django.db.models.functions import TruncMonthyear_month = models.Article.objects.filter(user=nid).extra(select={"y_m_date": "date_format(create_time,'%%Y-%%m')"}).values('y_m_date').annotate(c=Count("nid")).values_list('y_m_date', 'c')return render(request, "blog/home_site.html",{"username":username, "blog": blog, "article_list": article_list, "cate_list": cate_list, "tag_list": tag_list,"year_month": year_month})
V2
"""个人站点视图函数"""print("kwargs", kwargs)print("username",username)user = models.UserInfo.objects.filter(username=str(username)).first()if not user:return render(request, "blog/not_found.html")# 查询当前站点对象以及idblog = user.bloguserid = user.nidnid = blog.nid # 用作原地跳转标签匹配# 当前用户或者当前站点对应的所有文章article_list = models.Article.objects.filter(user=userid)if kwargs:condition = kwargs.get("condition")param = kwargs.get("param") # 2012-12if condition == "category":article_list = article_list.filter(category__title__icontains=param)elif condition == 'tag': # 通过tags字段回到Tagarticle_list = article_list.filter(tags__title__icontains=param)else:year, month = param.split("-")article_list = article_list.filter(create_time__year=year,create_time__month=month)# 查询当前站点的每一个分类名称以及对应的文章数目; 能用Article_category是因为article包含了外键categorycate_list = models.Category.objects.filter(blog__nid=nid).values_list("title").annotate(c=Count("Article_category"))# 查询当前站点的每一个标签名称以及对应的文章数tag_list = models.Tag.objects.values('pk').annotate(c=Count("article")).values_list("title", "c").filter(blog_id=nid)# 查询当前站点每一个年月的名称以及对应的文章数---单表分组查询# 引入函数专门处理日期分组:from django.db.models.functions import TruncMonthyear_month = models.Article.objects.filter(user=nid).extra(select={"y_m_date": "date_format(create_time,'%%Y-%%m')"}).values('y_m_date').annotate(c=Count("nid")).values_list('y_m_date', 'c')return render(request, "blog/home_site.html",{"username":username, "blog": blog, "article_list": article_list, "cate_list": cate_list, "tag_list": tag_list,"year_month": year_month})
数据备份
未辨明原因的数据查询
article_list2 = models.Article.objects.filter()print("---")print(article_list2)
可供选择的外键
Cannot resolve keyword 'UserInfo_username' into field. Choices are: Article_category, blog, blog_id, c, nid, title
对个人站点填充数据的数据库查询语句测试
cate_list = models.Category.objects.values("title").annotate(c=Count("Article_category")).filter(blog__title=blog)<QuerySet [{'title': 'DS', 'c': 2}]>cate_list = models.Category.objects.values("title").annotate(c=Count("Article_category")).filter(blog__nid=nid)<QuerySet [{'title': '前端', 'c': 1}, {'title': '软件工程', 'c': 1}]>cate_list = models.Category.objects.values("title").annotate(c=Count("Article_category")).filter(blog__nid=nid, blog__title=blog)<QuerySet []>cate_list=models.Category.objects.values("title").annotate(c=Count("Article_category")).filter(blog__nid=nid).filter(blog__title=blog)<QuerySet []>
home_site个人站点查询方法及结果保存
def home_site(request, username):"""个人站点视图函数"""print("username", str(username))user = models.UserInfo.objects.filter(username=str(username)).first()print('-------------')print(user)# 判断用户是否存在if not user:return render(request, "blog/not_found.html")# 查询当前站点对象blog = user.blogprint("个人站点标题")print(blog)nid = blog.nidprint("打印用户的blog_id")print(nid)# 当前用户或者当前站点对应的所有文章# https://docs.djangoproject.com/zh-hans/3.2/topics/db/examples/many_to_one/];2. 跨表查询# 1.基于对象user查询article_list = user.Article_user.all()print("---")print(article_list)# 2. 基于外键user_id反向查询article_list2 = models.Article.objects.filter(user=nid)print("---")print(article_list2)# 查询每一个分类名称以及对应的文章数,models.Category.objects.values("pk").annotate(c=Count("article__title"))cat_obj = models.Category.objects.values('pk').annotate(c=Count('Article_category')).values('c', 'title')print("打印分类名称以及对应的文章数" + str(cat_obj))print("---")ret = models.Category.objects.values("title").annotate(c=Count("Article_category"))print("---")print(ret)# 查询当前站点的每一个分类名称以及对应的文章数目; 能用Article_category是因为article包含了外键categorycate_list = models.Category.objects.filter(blog__nid=nid).values("title").annotate(c=Count("Article_category"))# models.Category.objects.filter(blog=blog).annotate(c=Count("Article_category"))print("---")print(cate_list)# 查询当前站点的每一个标签名称以及对应的文章数tags = models.Tag.objects.values('pk').annotate(c=Count("article")).values("title", "c").filter(blog_id=nid)print("标签名称以及对应的文章数" + str(tags))print("---")# 查询当前站点每一个年月的名称以及对应的文章数---单表分组查询era = models.Article.objects.extra(select={"is_recent": "create_time > '2021-09-07'"}).values("title", "is_recent")print(era)print("---")era_a = models.Article.objects.extra(select={"y_m_d_date": "date_format(create_time,'%%Y-%%m-%%d')"}).values('title', 'y_m_d_date')print(era_a)print("---")# 用article中的user字段匹配userinfo中的nidera_b = models.Article.objects.filter(user=nid).extra(select={"y_m_date": "date_format(create_time,'%%Y-%%m')"}).values('y_m_date').annotate(c=Count("nid")).values('y_m_date', 'c')print(era_b)print("---")# 引入函数专门处理日期分组:from django.db.models.functions import TruncMonthera_c = models.Article.objects.filter(user=nid).annotate(year_month=TruncMonth('create_time')).values('year_month').annotate(c=Count('nid')).values_list("year_month",'c')print(era_c)print("------------------------------------------")return render(request, "blog/home_site.html")
个人站点页面代码简化
def home_site(request, username):"""个人站点视图函数"""user = models.UserInfo.objects.filter(username=str(username)).first()if not user:return render(request, "blog/not_found.html")# 查询当前站点对象以及idblog = user.blognid = blog.nid# 当前用户或者当前站点对应的所有文章article_list = user.Article_user.all()# 查询当前站点的每一个分类名称以及对应的文章数目; 能用Article_category是因为article包含了外键categorycate_list = models.Category.objects.filter(blog__nid=nid).values_list("title").annotate(c=Count("Article_category"))# 查询当前站点的每一个标签名称以及对应的文章数tag_list = models.Tag.objects.values('pk').annotate(c=Count("article")).values_list("title", "c").filter(blog_id=nid)# 查询当前站点每一个年月的名称以及对应的文章数---单表分组查询# 引入函数专门处理日期分组:from django.db.models.functions import TruncMonthyear_month = models.Article.objects.filter(user=nid).extra(select={"y_m_date": "date_format(create_time,'%%Y-%%m')"}).values('y_m_date').annotate(c=Count("nid")).values_list('y_m_date', 'c')print(year_month)return render(request, "blog/home_site.html",{"blog":blog,"article_list":article_list,"cate_list":cate_list,"tag_list":tag_list,"year_month":year_month})
页面跳转[8,16,24]
<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 ym in year_month %}<p><a href="/{{ username }}/archive/{{ ym.0 }}">{{ ym.0 }}({{ ym.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>
测试URL路径
# 访问时间分类标签http://127.0.0.1:8001/alex/archive/2021-09/# 点击随笔分类 categoryhttp://127.0.0.1:8001/alex/category/alex%E7%9A%84DS/# 点击标签分类 t
状态保存
home_site.html
<!DOCTYPE html>{% load static %}<html lang="en"><head><meta charset="UTF-8"><title>个人站点表</title><link rel="stylesheet" href="{% static '/static/blog/bs/css/bootstrap.css' %}"><style>* {margin: 0;padding: 0;}.header {width: 100%;height: 60px;background-color: #d3dce6;}.header .title {font-size: 18px;font-weight: 100;line-height: 60px; /*设置上下居中*/color: lightpink;margin-left: 14px;margin-top: -10px;}.backend {float: right;color: darkslategrey;text-decoration: none; /*去掉多余的下划线*/font-size: 16px;margin-left: 10px;margin-top: 10px; /*文字下移*/}.pub_info {margin-top: 10px;color: springgreen;}</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="/{{ 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 ym in year_month %}<p><a href="/{{ username }}/archive/{{ ym.0 }}">{{ ym.0 }}({{ ym.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></body></html>
views.py—home_site
def home_site(request, username, **kwargs):"""个人站点视图函数"""print("kwargs", kwargs)print("username",username)user = models.UserInfo.objects.filter(username=str(username)).first()if not user:return render(request, "blog/not_found.html")# 查询当前站点对象以及idblog = user.bloguserid = user.nidnid = blog.nid # 用作原地跳转标签匹配# 当前用户或者当前站点对应的所有文章article_list = models.Article.objects.filter(user=userid)if kwargs:condition = kwargs.get("condition")param = kwargs.get("param") # 2012-12if condition == "category":article_list = article_list.filter(category__title__icontains=param)elif condition == 'tag': # 通过tags字段回到Tagarticle_list = article_list.filter(tags__title__icontains=param)else:year, month = param.split("-")article_list = article_list.filter(create_time__year=year,create_time__month=month)# 查询当前站点的每一个分类名称以及对应的文章数目; 能用Article_category是因为article包含了外键categorycate_list = models.Category.objects.filter(blog__nid=nid).values_list("title").annotate(c=Count("Article_category"))# 查询当前站点的每一个标签名称以及对应的文章数tag_list = models.Tag.objects.values('pk').annotate(c=Count("article")).values_list("title", "c").filter(blog_id=nid)# 查询当前站点每一个年月的名称以及对应的文章数---单表分组查询# 引入函数专门处理日期分组:from django.db.models.functions import TruncMonthyear_month = models.Article.objects.filter(user=nid).extra(select={"y_m_date": "date_format(create_time,'%%Y-%%m')"}).values('y_m_date').annotate(c=Count("nid")).values_list('y_m_date', 'c')return render(request, "blog/home_site.html",{"username":username, "blog": blog, "article_list": article_list, "cate_list": cate_list, "tag_list": tag_list,"year_month": year_month})
urls.py
"""whereabouts URL ConfigurationThe `urlpatterns` list routes URLs to views. For more information please see:https://docs.djangoproject.com/en/3.2/topics/http/urls/Examples:Function views1. Add an import: from my_app import views2. Add a URL to urlpatterns: path('', views.home, name='home')Class-based views1. Add an import: from other_app.views import Home2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')Including another URLconf1. Import the include() function: from django.urls import include, path2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))"""from django.contrib import adminfrom django.urls import path, include, re_pathfrom django.conf import settingsfrom django.conf.urls.static import staticfrom blog import viewsurlpatterns = [path('admin/', admin.site.urls),path('summernote/', include('django_summernote.urls')),# http://127.0.0.1:8001/login/path('login/', views.login),# http://127.0.0.1:8001/logout/path('logout/', views.logout),path('get_validCode_img/', views.get_validCode_img),# http://127.0.0.1:8001/index/path('index/', views.index),# http://127.0.0.1:8001/re_path('^$', views.index),# http://127.0.0.1:8001/registry/path('registry/', views.registry),# 个人站点的原地跳转[点击标签触发内容]re_path('^(?P<username>\w+)/(?P<condition>tag|category|archive)/(?P<param>.*)/$', views.home_site),# 个人站点URLre_path('^(?P<username>\w+)/$', views.home_site),# 文章页re_path('^(?P<username>\w+)/article/(?P<article_id>\d+)$', views.article_detail),]if settings.DEBUG:urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
Solved Problems
Database returned an invalid datetime value. Are time zone definitions for your database installed?
# 在settings中修改部分设置import datetimefrom django.utils.timezone import utcutcnow = datetime.datetime.utcnow().replace(tzinfo=utc)LANGUAGE_CODE = 'zh-Hans'TIME_ZONE = 'Asia/Shanghai'USE_I18N = TrueUSE_L10N = TrueUSE_TZ = False
可视化数据库软件DBeaver连接错误的
报错提示
Public Key Retrieval is not allowedhttps://blog.csdn.net/qq_42816401/article/details/91303134
处理办法

