Django之模型层多表操作的实现


当前第2页 返回上一页

3.1 正向查询(按属性:author)

# 金瓶眉所有作者的名字以及手机号
 
book_obj=Book.objects.filter(title="金瓶眉").first()
authors=book_obj.authors.all()
for author_obj in authors:
  print(author_obj.name,author_obj.authorDetail.telephone)

3.2 反向查询(按表名小写_set:book_set)

# 查询egon出过的所有书籍的名字
 
 author_obj=Author.objects.get(name="egon")
 book_list=author_obj.book_set.all()  #与egon作者相关的所有书籍
 for book_obj in book_list:
  print(book_obj.title)

4,related_name设置

可以通过Foreignkey和MangToMangField的定义中设置related_name的值来复写foo_set的名称。
publish=ForeignKey('Publish',related_name='booklist') #这样之后,反向就不用表名_set,就用booklist
# 查询 人民出版社出版过的所有书籍
publish=Publish.objects.get(name="人民出版社")
book_list=publish.bookList.all() # 与人民出版社关联的所有书籍对象集合

四、基于双下划线的跨表查询

Django还提供了一种直观而高效的方式在查询中表示关联关系,它能自动确认sql join联系。要做跨关系查询,就使用两个下划线来链接模型间关联字段的名称,直到最终连接到想要的model为止。

正向查询按属性,反向查询按表名小写

1,一对多查询

# 练习: 查询苹果出版社出版过的所有书籍的名字与价格(一对多)

 # 正向查询 按字段:publish

 queryResult=Book.objects
            .filter(publish__name="苹果出版社")
            .values_list("title","price")

 # 反向查询 按表名:book

 queryResult=Publish.objects
              .filter(name="苹果出版社")
              .values_list("book__title","book__price")

2,多对多查询

# 练习: 查询alex出过的所有书籍的名字(多对多)

 # 正向查询 按字段:authors:
 queryResult=Book.objects
            .filter(authors__name="yuan")
            .values_list("title")

 # 反向查询 按表名:book
 queryResult=Author.objects
              .filter(name="yuan")
              .values_list("book__title","book__price")

3,一对一关系

# 查询alex的手机号
 
 # 正向查询
 ret=Author.objects.filter(name="alex").values("authordetail__telephone")

 # 反向查询
 ret=AuthorDetail.objects.filter(author__name="alex").values("telephone")

4,进阶练习

# 练习: 查询人民出版社出版过的所有书籍的名字以及作者的姓名


 # 正向查询
 queryResult=Book.objects
            .filter(publish__name="人民出版社")
            .values_list("title","authors__name")
 # 反向查询
 queryResult=Publish.objects
              .filter(name="人民出版社")
              .values_list("book__title","book__authors__age","book__authors__name")


# 练习: 手机号以151开头的作者出版过的所有书籍名称以及出版社名称


 # 方式1:
 queryResult=Book.objects
            .filter(authors__authorDetail__telephone__regex="151")
            .values_list("title","publish__name")
 # 方式2: 
 ret=Author.objects
    .filter(authordetail__telephone__startswith="151")
    .values("book__title","book__publish__name")

五、聚合查询与分组查询

1,聚合

aggregate(*args,**kwargs)是Queryset的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是按照字段和聚合函数的名称自动生成出来的
计算所有图书的平均价格
from django.db.models import Avg
Book.objects.all().aggregate(Avg('price'))
结果:{'price__avg': 34.35}
如果你想要为聚合值指定一个名称,可以向聚合函数前面用一个变量名来接收,此时,键的名称就变为接收的变量名
Book.objects.aggregate(average_price=Avg('price'))
{'average_price': 34.35}
在终止子句里面可以放多个聚合函数,得到结果就是有多个键值对
from django.db.models import Avg, Max, Min
Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))
{'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}
aggregate()只能对一个分组有用,对于按某字段分完组后的n个组,此时aggregate()就不能循环对每个分组作用,它只会得到第一组的结果

2,分组

2.1 单表分组查询

查询每一个部门名称以及对应的员工数
emp:
id name age salary dep
 alex 12 2000  销售部
 egon 22 3000  人事部
 wen 22 5000  人事部
emp.objects.values('dep').annotate(c=Count('*'))
values(‘dep')就是按‘dep'进行分组
annotate()对每个分组的进行操作

2.2 多表分组查询

每一个出版社的名称和出版过的书籍个数
Publish.objects.values('name').annotate(c=Count('book'))  #首先读整个语句,当读到‘book'时,就会把两个表连起来,然后在按Publish.name分组
跨表分组查询本质就是将关联表join成一张表,然后再按单表的思路进行分组查询

还有一种写法:
publishlist=Publish.objects.annotate(c=Count('book')) 这相当于给Publish表添加了一个‘c'字段。首先也是把两张表连起来,以Publish分组,计算每个Publish的书籍数量
publishlist是一个queryset对象集合,里面放的是publish模型类对象,只是现在的对象比之前多了一个‘c'字段
for publish in publishlist:
  print(publish.name,publish.c) 利用for循环就可以遍历出每个模型类对象,然后用句点符‘.'就可以取得任何字段的值
我们也可以不用for循环,直接用values_list()就可以实现,如上面的for循环可以写成:values_list('name','c')

统计每一本书的作者个数
Book.objects.annotate(c=Count('author')).values_list('name','c')

filter()放在annotate()前面就是相当于where
统计每一本以py开头的书籍的作者的个数:
Book.objects.filter(name__startswith='py').annotate(c=Count('author')).values_list('name','c')

filter()放在annotate()后面就相当于having
统计作者个数大于1的书籍:
Book.objects.annotate(c=Count('author')).filter(c__gt=1).value_list('name','c')

根据书籍的作者数来排序:
Book.objects.annotate(c=Count('author')).orderby('c')

六、F查询与Q查询

1,F查询

在之前,对象的字段只能放在比较符的前面,比如filter(id__gt=2),但现在,有一个表,有生物成绩ss字段和物理成绩ws字段,统计物理成绩高于生物成绩的学生:
student.objects.filter(ws__gt=ss) 这样写肯定是报错的,因为字段写在了比较符后面,但此时我们借助F查询就可以不报错了,正确写法如下:
student.objcts.filter(ws__gt=F('ss')) F('ss')此时就是把ss字段的值取出来,就相当于一个纯数字了,可以进行加减乘除操作

查询物理成绩大于生物成绩两倍的学生
student.objects.filter(ws__gt=F('ss')*2)

把每个学生的物理成绩加上10分:
student.objects.all().update(ws=F('ws')+10)

2,Q查询

之前我们在用filter()时,可以用‘,'表示与关系,但没有或关系,现在我们用Q查询就可以实现或关系
Book.objects.filter(Q(id__gt=2)|Q(title__startswith='p')) 过滤出id大于2或者以‘p'开头的
Book.objects.filter(Q(id__gt=2)&Q(title__startswith='p')) 过滤出id大于2且以‘p'开头的
Book.objects.filter(Q(id__gt=2)|~Q(title__startswith='p')) 过滤出id大于2或不以‘p'开头的

Q查询可以和关键字参数混用,但Q()在前面
Book.objects.filter(Q(pub_date__year=2017)|Q(pub_date__year=2016),pub_date__month=2)过滤出2017年2月份或2016年2月份的书籍


标签:SQLite

返回前面的内容

相关阅读 >>

使用 sql 语句实现一个年会抽奖程序的代码

让python更加充分的使用Sqlite3

php登录验证功能示例【用户名、密码、验证码、数据库、已登陆验证、自动登录和注销登录等】

php出现内存位置访问无效错误问题解决方法

python pyqt5实战项目之查询器的实现流程详解

android调试工具adb命令大全

python操作Sqlite数据库的方法详解

android中的存储详解

linux中安装部署docker管理工具drone全攻略

c#中嵌入Sqlite数据库的简单方法

更多相关阅读请进入《Sqlite》频道 >>


数据库系统概念 第6版
书籍

数据库系统概念 第6版

机械工业出版社

本书主要讲述了数据模型、基于对象的数据库和XML、数据存储和查询、事务管理、体系结构等方面的内容。



打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...