整体设计思路
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 Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/3.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include, re_path
from django.conf import settings
from django.conf.urls.static import static
from blog import views
urlpatterns = [
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),
# 个人站点URL
re_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中nid
2. 在后台添加时则需要选择对应的个人站点,也就相当于第三列中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),
# 查询当前站点对象以及id
blog = user.blog
userid = user.nid
nid = 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字段回到Tag
article_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)
# 查询当前站点对象以及id
blog = user.blog
userid = user.nid
nid = blog.nid # 用作原地跳转标签匹配
# 当前用户或者当前站点对应的所有文章
if kwargs:
condition = kwargs.get("condition")
param = kwargs.get("param") # 2012-12
if condition == "category":
article_list = models.Article.objects.filter(category__blog=nid).filter(category__title__icontains=param)
elif condition == 'tag': # 通过tags字段回到Tag
article_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包含了外键category
cate_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 TruncMonth
year_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")
# 查询当前站点对象以及id
blog = user.blog
userid = user.nid
nid = blog.nid # 用作原地跳转标签匹配
# 当前用户或者当前站点对应的所有文章
article_list = models.Article.objects.filter(user=userid)
if kwargs:
condition = kwargs.get("condition")
param = kwargs.get("param") # 2012-12
if condition == "category":
article_list = article_list.filter(category__title__icontains=param)
elif condition == 'tag': # 通过tags字段回到Tag
article_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包含了外键category
cate_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 TruncMonth
year_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.blog
print("个人站点标题")
print(blog)
nid = blog.nid
print("打印用户的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包含了外键category
cate_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中的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')
print(era_b)
print("---")
# 引入函数专门处理日期分组:from django.db.models.functions import TruncMonth
era_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")
# 查询当前站点对象以及id
blog = user.blog
nid = blog.nid
# 当前用户或者当前站点对应的所有文章
article_list = user.Article_user.all()
# 查询当前站点的每一个分类名称以及对应的文章数目; 能用Article_category是因为article包含了外键category
cate_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 TruncMonth
year_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/
# 点击随笔分类 category
http://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")
# 查询当前站点对象以及id
blog = user.blog
userid = user.nid
nid = blog.nid # 用作原地跳转标签匹配
# 当前用户或者当前站点对应的所有文章
article_list = models.Article.objects.filter(user=userid)
if kwargs:
condition = kwargs.get("condition")
param = kwargs.get("param") # 2012-12
if condition == "category":
article_list = article_list.filter(category__title__icontains=param)
elif condition == 'tag': # 通过tags字段回到Tag
article_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包含了外键category
cate_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 TruncMonth
year_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 Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/3.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include, re_path
from django.conf import settings
from django.conf.urls.static import static
from blog import views
urlpatterns = [
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),
# 个人站点URL
re_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 datetime
from django.utils.timezone import utc
utcnow = datetime.datetime.utcnow().replace(tzinfo=utc)
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False
可视化数据库软件DBeaver
连接错误的
报错提示
Public Key Retrieval is not allowed
https://blog.csdn.net/qq_42816401/article/details/91303134