2.一对多
# 一对多新增 # 方式一 传对象的形式 pub_obj = models.Publish.objects.get(pk=1) # book = models.Book.objects.create(title="独孤九剑", price=140, pub_date="2008-08-23", publish=pub_obj) # 方式二 传对象id(用的更多) # book = models.Book.objects.create(title="冲灵剑法", price=140, pub_date="2018-08-23", publish_id=pub_obj.pk) print(book)#Book object (1) Book object (2)
3、多对多
方式1:
# 多对多的新增 # 方式1 传对象的形式 # book_obj = models.Book.objects.get(pk=1) # ling = models.Author.objects.get(pk=2) # ying = models.Author.objects.get(pk=3) # book_obj.authors.add(ling, ying)
方式2
# 插入对象的id
# 方式2 传对象的id
book_obj = models.Book.objects.get(pk=2)
ling = models.Author.objects.get(pk=2)
book_obj.authors.add(ling.pk)
注意:
不能使用关联管理器中的add方法就行使用:只能用在一对多的多的上面才行。(多对多也行)
# book_obj.publish.add(ling) 如果想在这个是多对一1,不能使用add关联其他的对象
2.关联管理器
2.1add方法
大前提: - 多对多,双向都有 - 一对多时,对应多的一方才有(出版社的角度),给1对多的1添加字段等于 一对多时,反向才能使用关联管理器
2.2 create方法(可以正向添加或者反向添加)
创建一个新的对象,保存对象,并将它添加到关联对象集之中。返回新创建的对象: >>> author_obj = Author.objects.get(id=1) >>> book = author_obj.book_set.create( ... title='挤奶龙爪手', ... ) # No need to call e.save() at this point -- it's already been saved. 这完全等价于(不过更加简洁于): >>> author_obj = Author.objects.get(id=1) >>> book = Book( ... title='挤奶龙爪手', ... ) >>> author_obj.save(force_insert=True) 要注意我们并不需要指定模型中用于定义关系的关键词参数。在上面的例子中,我们并没有传入author_obj参数给create()。Django会明白新的 Book对象author_obj 应该添加到author_obj中。
小结:
正向按字段名
方向按小写表名+ _set
例:
# create方法 ling = models.Author.objects.get(pk=2) ling.book_set.create(title="吸星大法", price=110, pub_date="2011-12-12", publish_id=1)
# 将数据加入app01_book中 并把它添加到关联的对象集中去。创建了2张表中的数据
创建上面的第三条数据。,
关系表中也创建了第4条数据。
4、基于对象的跨表查询
1、一对多查询(Publish 与 Book)
##### 基于对象的跨表查询#### # 一对多的关系: # 查询主键为1的书籍的出版社所在的城市 # 1.正向 book_obj = models.Book.objects.filter(pk=1).first() print(book_obj.publish.city) #华山 # 2.反向 # 查询华山出版社的出版的书籍名 # 分析先先查询华山的和book表关联的字段是id,于是先查出关联的字段 然后就行反查
# publish表中和app01_book表中关联的字段就是publish的id
pub_obj = models.Publish.objects.filter(name="华山出版社").first() for book in pub_obj.book_set.all(): print(book.title) return HttpResponse("查询成功!")
#独孤九剑
#冲灵剑法
#吸星大法
在创建类的时候,写的是关联的publish这个对象类,其实只是在内部关联的一个类默认创建的publish_id作为关联字段,即是传入的时候可以是对象和publish_id
4.2.一对一查询(Author 和 AuthorDetail)
# 反向时 直接小写的表名即可 不用_set # 查询林狐冲的电话 # 查询出林狐冲对象
# 正向查询 author_obj = models.Author.objects.filter(name="林狐冲").first() print(author_obj.au_detail.tel) 分析:电话在下一张的表中,于是我们把和下一张细节表相关的字段查出来。感觉就是自己找到相关联的字段就行跳到下一张表就行了!
反向查询(按表名:author):
# 查询所有住址在黑木崖的作者和姓名 au_detail_obj 对象也就是记录不知一条记录满足条件的!au在黑木崖的对象的单条()这里用了反向但是没有使用_set au_detail_obj = models.AuthorDetail.objects.filter(addr="黑木崖") for au in au_detail_obj: print(au.author.name) # 任我行 # 任盈盈
4.3、多对多查询 (Author 与 Book)
# 正向 # 独孤九剑度所有作者的名字以及手机号 # 分析 独孤九剑是书名肯定是在book表当中的,先把满足条件的记录即是对象的集合先拿出来 book_obj = models.Book.objects.filter(title="独孤九剑").first() # 写独孤九剑的作者不只一个 for au in book_obj.authors.all(): print(au.name, au.au_detail.tel) # 任我行 13943454554 # 任盈盈 13878934322
分析:书表和作者表通过,authors字段就行关联,作者表和作者详细信息表之间通过au_detail字段就行关联,直接一直找去下就完事!
5.基于双下划线的跨表查询(****)
# 一对多关系: # 练习: 查询华山出版社出版过的所有书籍的名字与价格(一对多)(publish__name已经跨表了)
#
分析:查询的是华山出版社的书籍名字和价格,需要的是名字和价格在book表中,出版社的字样是在publish的表中
第一种:从book表开始往下面查即是正向查询,直接在过滤的时候使用publish_name就行跳表条件就行过滤!
第二种:从publish表开始往上边查即是反向查询,
# 正向: # book = models.Book.objects.filter(publish__name="华山出版社").values("title", "price")
运行结果: <QuerySet [
{'title': '独孤九剑', 'price': Decimal('140.00')},
{'title': '冲灵剑法', 'price': Decimal('140.00')},
{'title': '吸星大法', 'price': Decimal('110.00')}
]>
# 反向查询 按表名:book book = models.Publish.objects.filter(name="华山出版社").values("book__title", "book__price") print(book) 运行结果: <QuerySet [ {'book__title': '独孤九剑', 'book__price': Decimal('140.00')},
{'book__title': '冲灵剑法', 'book__price': Decimal('140.00')},
{'book__title': '吸星大法', 'book__price': Decimal('110.00')} ]>
# 多对多关系: # 练习: 查询令狐冲出过的所有书籍的名字(多对多) # 正向 # 分析:需要的是所有书籍的名字,在book表中,其次就是在作者表中去查询是令狐冲的的id是多少即是author_id # 正向 book = models.Book.objects.filter(authors__name="令狐冲").values("title") print(book) # 反向 book = models.Author.objects.filter(name="令狐冲").values("book__title") print(book)
<QuerySet []>
<QuerySet [{'book__title': None}]>
小结:多对多之间,author和 book 、publish之间,有关联的话直接跳就行了。
# 一对1的练习
# 查询令狐冲的手机号 # 正向 book = models.Author.objects.filter(name="令狐冲").values('au_detail__tel') print(book) book = models.AuthorDetail.objects.filter(author__name="令狐冲").values('tel') print(book)
# <QuerySet [{'au_detail__tel': '13432335433'}]>
# <QuerySet [{'tel': '13432335433'}]>
# 综合练习
# 练习1: 查询华山出版社出版过的所有书籍的名字以及作者的姓名 # 正向 book = models.Book.objects.filter(publish__name="华山出版社").values('title', 'authors__name') print(book) # 反向 book = models.Publish.objects.filter(name="华山出版社").values("book__title", "book__authors__name") print(book) # 正向运行结果: <QuerySet [
{'title': '独孤九剑', 'authors__name': '任我行'},
{'title': '冲灵剑法', 'authors__name': '任我行'},
{'title': '吸星大法', 'authors__name': '任我行'},
{'title': '独孤九剑', 'authors__name': '任盈盈'}]> # 反向运行结果: <QuerySet [
{'book__title': '独孤九剑', 'book__authors__name': '任我行'},
{'book__title': '冲灵剑法', 'book__authors__name': '任我行'},
{'book__title': '吸星大法', 'book__authors__name': '任我行'},
{'book__title': '独孤九剑', 'book__authors__name': '任盈盈'}]>