我的数据库是按照下面的图片的方式设计的

然后看下model中代码

class User(models.Model):
uid = models.AutoField(primary_key=True)
username = models.CharField(max_length=32,unique=True)
def __str__(self):
return self.username
class Meta:
verbose_name = "博客用户表"
verbose_name_plural = verbose_name class Blog(models.Model):
bid = models.AutoField(primary_key=True)
blog_title = models.CharField(max_length=32,verbose_name="博客标题")
blog_site = models.OneToOneField(to="User",to_field="uid",verbose_name="博客网址",on_delete=True) def __str__(self):
return self.blog_title
class Meta:
verbose_name = "博客表"
verbose_name_plural = verbose_name class Article(models.Model):
aid = models.AutoField(primary_key=True)
title = models.CharField(max_length=50, verbose_name="文章标题") # 文章标题
desc = models.CharField(max_length=255) # 文章描述
create_time = models.DateTimeField()
category = models.ForeignKey(to="Category", to_field="cid", null=True,on_delete=True)
def __str__(self):
return self.title class Meta:
verbose_name = "文章表"
verbose_name_plural = verbose_name class Category(models.Model):
cid = models.AutoField(primary_key=True)
category_title = models.CharField(max_length=32) # 分类标题
blog = models.ForeignKey(to="Blog", to_field="bid",on_delete=True) # 外键关联博客,一个博客站点可以有多个分类 def __str__(self):
return self.category_title class Meta:
verbose_name = "文章分类"
verbose_name_plural = verbose_name class Tag(models.Model):
tid = models.AutoField(primary_key=True)
title = models.CharField(max_length=64,default="xxx")
tag_title = models.ManyToManyField(to="Article",)
tag_blog = models.ForeignKey(to="Blog", to_field="bid",on_delete=True) # 所属博客 def __str__(self):
return self.title
class Meta:
verbose_name = "标签表"
verbose_name_plural = verbose_name

表结构梳理

a、用户表和博客表是一对一的关系

b、文章分类表和博客是多对一的关系,即一个博客可以有多个分类

c、文章标签表和博客是多对一的关系,即一个博客可以有多个标签

d、文章和分类表是多对一的关系,一个文章只能有一个分类,而一个分类中可以有多个文章

e、文章和标签表是多对多的关系,一个文件可以有多个标签,而一个标签中可以有多个文章

现在的场景如下

一个用户过来访问数据库,比如test1,我们通过用户拿到这个用户对应的blog的对象,通过blog对象拿到这个blog对象的文章分类的对象,然后按照文章分类的id做分组计算,通过跨表查询获取每个分类下的文章

代码如下

    from app1 import models
from django.db.models import Count
# a、通过用户名找到该用户对应的博客的对象
obj = models.User.objects.filter(username="test1")[0].blog
print(obj, type(obj)) # 方法1、通过分组聚合的方式
# b、通过博客找到这个博客的所有的分类,然后按照分类的ip进行分组统计,统计每个分类的下的文章的数量
# obj = obj.category_set.all().values("cid").annotate(c=Count("article__aid")).values("category_title","c","cid")
# print(obj) # 方法2、通过跨表查询的方式
obj = obj.category_set.all()[0].article_set.all().count()
print(obj)

同样,如果我们要计算某个人的博客下的每个标签的文章,思路是一样的

    obj = models.User.objects.filter(username="test1")[0].blog

    obj = obj.tag_set.all().values("tid").annotate(c=Count("tag_title__aid")).values("title","c")
print(obj) obj = models.User.objects.filter(username="test1")[0].blog obj = obj.tag_set.all()[3].tag_title.count()
print(obj)

关于反向查询还是有点不清楚,用下面这个例子在来巩固一下

    from app1 import models
from django.db.models import Count
# a、通过用户名找到该用户对应的博客的对象
obj = models.User.objects.filter(username="test1")[0].blog # 1、通过对象进行反向查询
category_obj = obj.category_set.all()
article_obj = category_obj.values("article__title")
print(article_obj)

 

下面解释一下上面的代码

obj = models.User.objects.filter(username="test1")[0].blog

a、首先通过用户的名字找到这个用户在User表中的queryset对象
b、然后通过索引取第一个,拿到一个具体的用户对象
c、最后,由于blog表和 User表是一对一的关系,但是一对一的字段blog_site字段在blog表中,我们如果想通过User表找到Blog表的对象,就只能通过表名,这里就要注意,虽然我们的表名叫做Blog,但是这里必须要全小写,所以通过.blog拿到这个用户的Blog对象

category_obj = obj.category_set.all()

a、首先我们在上一段中拿到Blog对象,我们要通过Blog对象拿到这个对象的category信息,由于Blog表和Category是外键的关系,但是外键字段在Category表中,且由于上一步我们拿到的是一个具体的Blog对象,所以可以使用“表名”+"_set"方法去做跨表查询,这里就拿到这个Blog对象对应的Category的queryset对象,然后调用all方法,拿到所有的Category对象

article_obj = category_obj.values("article__title")

a、上一步我们拿到一个category的queryset对象,然后我们调用values方法去拿到这个category对象对应的文章的标题
b、由于category和article是外键的关系,且外键字段在article表中,这里如何通过category对象去获取article表的信息呢?这里也可以也要通过“表名”+“__”双下划线去做跨表查询

这里我们要非常注意,如果是反向查询
如果是具体的对象,格式为“表名”+"_set"的方式进行跨表查询,切记这里的表名是全小写
如果是queryset的对象,可以在values中做跨表查询,格式为“表名”+“__”,表名+双下划线的方式做跨表查询,切记这里的表名是全小写

我们在看下例子

obj = models.User.objects.filter(username="test1")[0].blog
category_obj = obj.category_set.all()
article_obj2 = category_obj[0].article_set.values("title")
print(article_obj2)
obj = models.User.objects.filter(username="test1")[0].blog

a、同上

category_obj = obj.category_set.all()

a、同上

article_obj2 = category_obj[0].article_set.values("title")

a、上一步我们拿到一个分类的queryset对象。然后通过索引取第一个元素,拿到的就是一个具体的分类的对象
b、由于是具体的对象,我们如果要进行反向查询,则可以使用“表名”+“_set”的方法做反向查询。拿到这个分类对应的文章表对应的所以的文章对象,拿到文章对象后,由于文章对象有和title字段,所以这里就不需要做什么跨表查询,直接可以使用文章表中的字段title进行打印即可

bbs项目中对反向查询和分组查询的具体的应用的更多相关文章

  1. Web框架之Django_05 模型层了解(单表查询、多表查询、聚合查询、分组查询)

    摘要: 单表查询 多表查询 聚合查询 分组查询 一.Django ORM 常用字段和参数: 常用字段:#AutoFieldint自增列,必须填入参数primary_key = True,当model中 ...

  2. python全栈开发day68-ORM操作:一般操作、ForeignKey操作、ManyToManyField、聚合查询和分组查询、F查询和Q查询等

    ORM操作 https://www.cnblogs.com/maple-shaw/articles/9403501.html 一.一般操作 1. 必知必会13条 <1> all(): 查询 ...

  3. {django模型层(二)多表操作}一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询、分组查询、F查询和Q查询

    Django基础五之django模型层(二)多表操作 本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 xxx 七 ...

  4. 基于对象的跨表查询,多对多查询,多对多操作,聚合查询和分组查询,F查询和Q 查询

    基于对象的跨表查询 一对多查询(班级表和学生表) 表结构创建 class Class(models.Model): id = models.AutoField(primary_key=True) cn ...

  5. Django【第7篇】:Django之ORM跨表操作(聚合查询,分组查询,F和Q查询等)

    django之跨表查询及添加记录 一:创建表 书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many); ...

  6. Django框架(十)—— 多表操作:一对一、一对多、多对多的增删改,基于对象/双下划线的跨表查询、聚合查询、分组查询、F查询与Q查询

    目录 多表操作:增删改,基于对象/双下划线的跨表查询.聚合查询.分组查询.F查询与Q查询 一.创建多表模型 二.一对多增删改表记录 1.一对多添加记录 2.一对多删除记录 3.一对多修改记录 三.一对 ...

  7. 第十七篇 ORM跨表查询和分组查询---二次剖析

    ORM跨表查询和分组查询---二次剖析 阅读目录(Content) 创建表(建立模型) 基于对象的跨表查询 一对多查询(Publish与Book) 多对多查询 (Author 与 Book) 一对一查 ...

  8. ORM单表查询,跨表查询,分组查询

    ORM单表查询,跨表查询,分组查询   单表查询之下划线 models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值models ...

  9. 6月21日 Django ORM那些相关操作(表关联、聚合查询和分组查询)

    一.ForeignKey操作 正向查找 对象查找(跨表) 语法: 对象.关联字段.字段   示例: book_obj = models.Book.objects.first() # 第一本书对象 pr ...

随机推荐

  1. 笨方法学python之读写文件、open函数的用法

    一.python读写文件相关知识点 close:关闭文件 read:读取文件的内容//你可以把结果赋给一个变量 readline:只读取文件中的一行 truncate 美 /trʌŋ'ket/ :清空 ...

  2. js的非空校验

    利用TagName获取元素名称,进行批量非空校验 var input = document.getElementsByTagName("input"); for (var i=0; ...

  3. Haskell语言学习笔记(72)Free Monad

    安装 free 包 $ cabal install free Installed free-5.0.2 Free Monad data Free f a = Pure a | Free (f (Fre ...

  4. C#格式化数值结果表(格式化字符串)

    字符 说明 示例 输出 C 货币 string.Format("{0:C3}", 2) $2.000 D 十进制 string.Format("{0:D3}", ...

  5. MVC缺点总结

    MVC的缺点: 1.完全理解MVC比较复杂. 由于MVC模式提出的时间不长,加上同学们的实践经验不足,所以完全理解并掌握MVC不是一个很容易的过程. 2.调试困难. 因为模型和视图要严格的分离,这样也 ...

  6. PS常用快捷键(收藏)

    一.工具箱(多种工具共用一个快捷键的可同时按[Shift]加此快捷键选取) 矩形.椭圆选框工具 [M] 移动工具 [V] 套索.多边形套索.磁性套索 [L] 魔棒工具 [W] 裁剪工具 [C] 切片工 ...

  7. <assert.h>库学习

    assert的初步认识 assert宏指令是用来诊断程序是否有误的,函数原型如下 void assert(int expression) 那为什么我们要使用assert而不用printf呢?因为ass ...

  8. linux 内核启动流程

    Linux内核启动流程详细分析: http://www.linuxidc.com/Linux/2014-10/108034.htm ARM Linux内核启动过程: http://blog.csdn. ...

  9. js模板引擎用法

    JavaScript模板引擎Template.js使用详解 作者:A_山水子农 字体:[增加 减小] 类型:转载 时间:2016-12-15我要评论 这篇文章主要为大家详细介绍了JavaScript模 ...

  10. Linus运行jar包的操作

    cd /    返回最顶层文件夹cd home/numa        进入home下的numa文件夹ll         查看当前文加夹下的所有文件ps -ef | grep java        ...