多表查询:
KEY ====》 通过 ORM 引擎如何跨表: 正向查询按字段, 反向查询按表名小写
模型的创建:
- from django.db import models
- # Create your models here.
- class Book(models.Model):
- title = models.CharField(max_length=32)
- pub_date = models.DateField()
- price = models.DecimalField(max_digits=6,decimal_places=2)
- #publish 和 book 是一对多额关系
- publish = models.ForeignKey(to="Publish",on_delete=models.CASCADE)
- #book 和 author 表示多对多关系
- authors = models.ManyToManyField(to="Author",db_table="book2authors")
- def __str__(self):
- return self.title
- class Publish(models.Model):
- name = models.CharField(max_length=32)
- city = models.CharField(max_length=32)
- email = models.CharField(max_length=32)
- def __str__(self):
- return self.name
- class Author(models.Model):
- name = models.CharField(max_length=32)
- age = models.IntegerField()
- #作者与作者详细信息时一对一关系
- ad = models.OneToOneField(to="AuthorDetail",on_delete=models.CASCADE)
- def __str__(self):
- return self.name
- class AuthorDetail(models.Model):
- brithday = models.DateField()
- tel = models.BigIntegerField()
- addr = models.CharField(max_length=64)
- def __str__(self):
- return str(self.tel)
一 基于对象的跨表查询( 子查询: 以上一次的查询结果作为下一次的查询条件)
(1)一对多
正向查询: 按字段 book.publish
Book 对象 ----------------------------------> Publish 对象
<---------------------------------
反向查询: 按表名小写_set.all()
(2)多对多
正向查询: 按字段 book.authors.all()
Book 对象 ----------------------------------> Author 对象
<---------------------------------
反向查询: 按表名小写_set.all() ,# 表名_set .all () 此处的 set 表示集合的意思
(3)一对一
正向查询: 按字段 book.ad
Author 对象 ----------------------------------> AuthorDetail 对象
<---------------------------------
反向查询: 按表名小写
二 基于双下划綫的跨表查询:(相当于 MySQL 中的 join)
left join on
通过 表名__该表名字段 ="条件" , 表名__ 表示连表
结构: models.Book.objects.filter(条件).values(需要查询的字段)
- #多表操作 ======》添加 defadd(request):
- ############################### 绑定一对多关系 ############################################################
- #方式一
- # book = models.Book.objects.create(title="python", price=123, pub_date="2019-01-02", publish_id=1)
- pub_obj = models.Publish.objects.filter(name="苹果出版社").first()
- #
- # book = models.Book.objects.create(title="python",price=123,pub_date="2019-01-02",publish=pub_obj)
- # print(book.title) #python
- # print(book.publish_id) #2
- # print(book.publish)# 苹果出版社, 打印对象时,__str__ 返回的值
- # 查询 go 出版社的邮箱
- # book_go = models.Book.objects.filter(title="go").first()
- # print(book_go.publish.email)
- ############################# 绑定多对多关系, 无非是在关系表中创建记录 ######################################
- # Linux 这本书绑定两个作者: alex,egon
- Linux = models.Book.objects.filter(title="linux").first()
- alex = models.Author.objects.filter(name="alex").first()
- egon = models.Author.objects.filter(name="egon").first()
- # Linux.authors.add(alex.id,egon.id) #为什么不是这样写
- # Linux.authors.add(alex,egon) #重复的作者不会添加, 不知道主键时用这种方式添加
- # Linux.authors.add(1,2) #这个也可以, 已经知道主键用这种方式添加
- # Linux.authors.add(*[2,1])# 相当于打散, 一个个赋值
- # Linux.authors.remove(egon) #移除
- # Linux.authors.clear() 解除所有绑定
- # Linux.authors.set(1) #不能这样写
- # Linux.authors.set([1,]) #先清空, 再添加, 参数必须为一个列表
- #
- # 绑定多对多的方式: 一定要找到关联属性在哪里, manytomany 关联属性 authors,
- # book. 关联属性. add() book. 关联属性. set([,]),book. 关联属性. clear()
- #正向操作 (关联字段所在的那个表开始) 按字段, 反向操作按表名小写
- #给 Alex 添加两个书
- Linux = models.Book.objects.filter(title="linux").first()
- go = models.Book.objects.filter(title="go").first()
- alex = models.Author.objects.filter(name="alex").first()
- #给 Alex 作者绑定两本书籍: Linux 和 go
- alex.book_set.add(Linux,go)
- return HttpResponse("添加成功!")
- # 一对一表的添加和一对多类似 作者表和作者详细表
- # 多表操作 ========》查询
- def query(request):
- ################################################## 基于对象的跨表查询 ############################################
- # (1) 一对多
- #1 查询 Linux 这本书籍的出版社的地址
正向查询
- # Linux = models.Book.objects.filter(title="linux").first()
- # print(Linux.publish.city)
- # 2 查询苹果出版社出版的所有书籍
反向查询
- # obj = models.Publish.objects.filter(name="苹果出版社").first()
- # query = obj.book_set.all()
- # print(query)
- # (2) 多对多
- # 1 查询 Linux 书籍的所有作者
- # Linux = models.Book.objects.filter(title="linux").first()
- # print(Linux.authors.all())
- # 2 查询 alex 作者出版过得所有书籍
- # alex = models.Author.objects.filter(name="alex").first()
- # print(alex.book_set.all())
- # (3)一对一
- # 1 查询 alex 的手机号
- # alex = models.Author.objects.filter(name="alex").first()
- # print(alex.ad.tel)
- # 2 查询手机号为 911 的作者的名字
- # obj = models.AuthorDetail.objects.filter(tel=911).first()
- # print(obj.authors.name)
- ########################################### 基于双下划线的跨表查询 ##################################################
- # 1 查询 Linux 这本书籍的出版社的地址
- # 方式一
- # queryset = models.Book.objects.filter(title="linux").values("publish__city")
- # print(queryset)
- # print(queryset[0]["publish__city"])
- # return HttpResponse("查询成功!")
- #方式二
- # queryset = models.Publish.objects.filter(book__title="linux").values("city")
- # print(queryset)
- # return HttpResponse("查询成功")
- # 2 查询 Linux 书籍的所有作者
- #正向查询
- # queryset = models.Book.objects.filter(title="linux").values("authors__name")
- # print(queryset)
- #反向查询
- # queryset = models.Author.objects.filter(book__title="linux").values("name")
- # print(queryset)
- # 3 查询 alex 的手机号
- #正向查询
- # queryset = models.Author.objects.filter(name="alex").values("ad__tel")
- # print(queryset)
- #反向查询
- # queryset = models.AuthorDetail.objects.filter(author__name="alex").values('tel')
- # print(queryset)
- # 连续跨表
- # 4 查询人民出版社出版过的所有书籍的名字以及作者的姓名
- # queryset = models.Book.objects.filter(publish__name="人民出版社").values("title","authors__name")
- # print(queryset)
- # queryset = models.Author.objects.filter(book__publish__name="人民出版社").values("book__title","name")
- # print(queryset)
- # 5 手机号以 119 开头的作者出版过的所有书籍名称以及出版社名称
- queryset = models.Book.objects.filter(authors__ad__tel__startswith=119).values("title","publish__name")
- print(queryset)
- return HttpResponse("查询成功")
待续
来源: http://www.bubuko.com/infodetail-2909392.html