Django(7) 多表查询

图书管理系统

1、先创建关于图书管理系统的表
# 第一张 图书详情表
class Bookz(models.Model):
  title = models.CharField(verbose_name='书名',max_length=32)
  price = models.DecimalField(verbose_name='价格',max_digits=8,decimal_places=2)
  publish_time = models.DateField(verbose_name='出版时间', auto_now_add=True)
 # 建立一对多的外健关系
	publish = models.ForeignKey(to='Publushz')
 # 书和作者是多对多的瓜系
  Authors = models.ManyToManyField(to='Authorz')

 class Publishz(models.Model):
  title = models.CharField(verbose_name='名称',max_length=32)
  addr = models.CharField(verbose_name='地址',max_length=128)
  email = models.EmailField(verbose_name='邮箱')

 class Authorz(models.Model):
	name = models.CharField(verbose_name='姓名',max_length=32)
  age = models.IntegerField(verbose_name='年龄')
 # Author和Authorz是一对一的关系
  author_Detail = models.OneToOneField(to='AuthorDetailz')
2、进行数据库迁移
python3 manage.py makemigrations;
python3 manage.py migrate;



3、到test.py --> 自己创的测试文件
🌹 一对多
(1) 添加外键字段
方式1 直接添加 models.Bookz.objects.create(title='dog_journey',price=12,publish_id=1)
(2) 创建对象添加
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Bookz.objects.create(title='dog_journey',price=12,publish_id=publish_obj)
(2)更改外键字段
方式1 直接更改
models.Bookz.objects.filter(pk=1).update(publish_id=2)
方式2 创建对象修改
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Bookz.objects.filter(pk=1).update(publish_id=publish_obj)

🌹 多对多
(1) 添加外键字段 add
方式1
book_obj=models.Bookz.objects.filter(pk=1).first()
book_obj.Authors.add(1) -->Authors是bookz表创建多对多外键的(可以去上面看看),括号里可以直接写数字,也可以写多个数字
方式2 
Author_obj=models.Authorz.objects.filter(pk=1).first()
bookz_obj=models.Bookz.objects.filter(pk=3).first()
bookz_obj.Authors.add(Author_obj) --> 括号里写的是对象
(2) 更改外键字段 set
book_obj=models.Bookz.objects.filter(pk=1).first()
book_obj.Authors.set(1) 错的<-->对的 book_obj.Authors.set((1,)) --> 这里必须得写可叠代对象,比如列表,元组等
同理也有方式2,set() 括号里可以写对象
(3) 删 remove 
book_obj=models.Bookz.objects.filter(pk=1).first()
book_obj.Authors.remove(1)
(4) 清空
book_obj=models.Bookz.objects.filter(pk=1).first()
book_obj.Authors.clear()-->第三张表中的pk=1的书都是没有绑定了

基于对象的正反向查询

基于对象的查询,其实就是mysql的子查询
1、先查处一个对象 2、基于对象点反向字段
正向查询:本身有外键字段区查别人
反向查询:本身没有外键区查别人

当然其实是没有正反向的,都是后期整理的
正向查询按外键字段,反向查询按表名小谢,在查询对象有多个的时候需要_set

例题
# 正向查询
(1)查询cat_journry所对应的出版社名称
	book_obj=models.Bookz.objects.filter(title='cat_journey').first()
	res=book_obj.publish
	print(res.title)
(2)查询dog_journey所对应的作者	
	book_obj=models.Bookz.objects.filter(title='dog_journey').first()
	res=book_obj.Authors.all()
	print(res[0].name) 

	res = models.Bookz.objects.filter(title='dog_journey').first()
	print(res.Authors.all())
(3)查询judy的地址
	author_obj = models.Authorz.objects.filter(name='judy').first()
	res = author_obj.author_Detail
	print(res.addr)
# 反向查询
(4)查询东方出版社出版过的书
	publish_obj=models.Publishz.objects.filter(title='东方出版社').first()
	res=publish_obj.bookz_set.all()
	print(res)
	# <QuerySet [<Bookz: Bookz object>, <Bookz: Bookz object>]>
	print(res.last().title)
	print(res.first().title)
	print(res[0].title)
	# 可以根据索引拿,也可以用first()和last函数拿
(5)查amber写过的书
	author_obj=models.Authorz.objects.filter(name='amber').first()
	res=author_obj.bookz_set.all()
	print(res.first().title)
(6)查询电话时123的作者姓名
	author_detail_obj=models.AuthorDetailz.objects.filter(phone=123).first()
	res=author_detail_obj.authorz
	print(res.name)

基于双下划线的正反向查询

这种查询相当于mysql的链表查询

例题
# 正向查询 找什么,所在表有外键的时候可以用正向查询,先创建寻找对象所在的表
(1)查询cat_journry所对应的出版社名称
	res = models.Bookz.objects.filter(title='cat_journey').values('publish__title')-->这里publish用的是外键
	# print(res.first()) # {'publish__title': '东方出版社'}
	res1=res.first()
	print(res1.get('publish__title')) # 只能用get方法拿,不能用[]这个方法拿,拿不了
(2)查询dog_journey所对应的作者	
	res = models.Bookz.objects.filter(title='dog_journey').values('Authors__name')-->这里Authors用的是外键
	# print(res) #<QuerySet [{'Authors__name': 'judy'}, {'Authors__name': 'amber'}]>
	print(res[0].get('Authors__name'))
	print(res[1].get('Authors__name'))

(3)查询judy的地址
   res = models.Authorz.objects.filter(name='judy').values('author_Detail__addr')
	print(res.first()) # {'author_Detail__addr': '杭州'}
	print(res.first().get('author_Detail__addr')) # 杭州

# 反向查询
(1)查出cat_journey对应的出版社名称
res = models.Publishz.objects.filter(bookz__title='cat_journey').values('title')
print(res.first()) # {'title': '东方出版社'}
(2)查询dog_journey对应的作者名字
res = models.Authorz.objects.filter(bookz__title='dog_journey').values('name')
print(res) # <QuerySet [{'name': 'judy'}, {'name': 'amber'}]>
(3)查询judy的地址
res = models.AuthorDetailz.objects.filter(authorz__name='judy').values('addr')
print(res) # <QuerySet [{'addr': '杭州'}]>
🌹 --->事实上没有正反向一说,学会用就行了

聚合查询

max min avg count sum 聚合函数必须结合aggregate使用
1、要使用聚合函数得先导入聚合函数
from django.db.models import Sum,Avg,Max,Min,Count

# (1)计算所有书的平均价格
# 第一步 先导入
from django.db.models import Sum,Avg,Max,Min,Count
# res = models.Bookz.objects.all().aggregate(Avg('price'))
# print(res)
# (2) 计算所有书的总价格
# res = models.Bookz.objects.all().aggregate(Sum('price'))
# print(res)
# (3) 计算所有书的价格中的最大值
# res = models.Bookz.objects.all().aggregate(max_total=Max('price'))  --> 🌹 可以重命名 max_total=Max('price')
# print(res)
# (4)计算一共有几本书
# res = models.Bookz.objects.all().aggregate(Count('id'))
# print(res)
# (5) 东方出版社出版的书的总价格
res = models.Bookz.objects.filter(publish__title='东方出版社').aggregate(Sum('price'))
print(res) # {'price__sum': Decimal('30.00')}

F查询

F函数-->去除某个字段对应的值
	# (1) 查询评论数比阅读数多的书籍
	from django.db.models import F,Q
	res = models.Bookz.objects.filter(read_num__lt=F('comment_num'))
	print(res) #<QuerySet [<Bookz: cat_journey>, <Bookz: dog_journey>]>
	# (2) 将书籍的价格都加上1块钱
	res=models.Bookz.objects.update(price=F('price')+1)
	这里的res是影响的行数

Q查询

Q查询时构造与或非
	# Q函数 构造出与(&)或(|)非(~)
	# (1) 查询名字叫cat_journey或者价格大于10块的书
	res = models.Bookz.objects.filter(Q(title='cat_journey')|Q(price__gt=10))
	print(res) # <QuerySet [<Bookz: cat_journey>, <Bookz: dog_journey>, <Bookz: rabbit_journey>]>
	 # (2) 查询名字不是cat_journey的书
	res = models.Bookz.objects.filter(~Q(title='cat_journey'))
	print(res) #<QuerySet [<Bookz: dog_journey>, <Bookz: rabbit_journey>]>

	# (3) 查询名字不是dog_journey并且价格大于10块的书
	# res = models.Bookz.objects.filter(~Q(title='dog_journey'), price__gt=15)
	# print(res)
🌹 如果是与的话,可以直接用,代替
posted @ 2022-02-23 22:04  JudyJU  阅读(45)  评论(0)    收藏  举报