day 48 ORM 进阶 多表连接 创建 以及 html模板继承

    多表的一对多创建

   多表的多对多创建

   多表的一对多修改

   多表的多对多修改

前情提要:  

  最近认识了不少大佬,大佬开着保时捷. .一顿狂奔..我连车尾灯都看不到..

  本次内容  ORM 的多表链接  查询    ,  html的模板继承

 

   2、添加表记录

      方式一:

        通过类实例化对象的方式。注意:一定要对象.save()

1
2
book = models.Book(title="吸星大法", price=200, publisher="明教出版社", pub_date="2018-12-12")
book.save()

      方式二:

        通过ORM提供的objects提供的方法 create来实现。

1
book = models.Book.objects.create(title="独孤九剑", price=150, publisher="华山出版社", pub_date="2019-1-12")
    3、查询表记录

      1、查询API

复制代码
<1> all():                  查询所有结果
  
<2> filter(**kwargs):       它包含了与所给筛选条件相匹配的对象
  
<3> get(**kwargs):          返回与所给筛选条件相匹配的对象,返回结果有且只有一个,
                            如果符合筛选条件的对象超过一个或者没有都会抛出错误。
  
<4> exclude(**kwargs):      它包含了与所给筛选条件不匹配的对象
 
<5> order_by(*field):       对查询结果排序
  
<6> reverse():              对查询结果反向排序
  
<7> count():                返回数据库中匹配查询(QuerySet)的对象数量。
  
<8> first():                返回第一条记录
  
<9> last():                返回最后一条记录
  
<10> exists():              如果QuerySet包含数据,就返回True,否则返回False
 
<11> values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列
                            model的实例化对象,而是一个可迭代的字典序列
<12> values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
 
<13> distinct():            从返回结果中剔除重复纪录
复制代码

      2、基于双下划线的模糊查询

1
2
3
4
5
6
7
8
Book.objects.filter(price__in=[100,200,300])
Book.objects.filter(price__gt=100)
Book.objects.filter(price__lt=100)
Book.objects.filter(price__range=[100,200])
Book.objects.filter(title__contains="法")
Book.objects.filter(title__icontains="python")  # 不区分大小写
Book.objects.filter(title__startswith="九")
Book.objects.filter(pub_date__year=2018)
    4、删除表记录

      删除方法就是 delete()。它运行时立即删除对象而不返回任何值。例如:

1
model_obj.delete()

      你也可以一次性删除多个对象。每个 QuerySet 都有一个 delete() 方法,它一次性删除 QuerySet 中所有的对象。

      例如,下面的代码将删除 pub_date 是2018年的 Book 对象:

1
Book.objects.filter(pub_date__year=2018).delete()

      在 Django 删除对象时,会模仿 SQL 约束 ON DELETE CASCADE 的行为,换句话说,删除一个对象时也会删除与它相关联的外键对象。例如:

1
2
3
= Book.objects.get(pk=1)
# This will delete the Blog and all of its Entry objects.
b.delete()

要注意的是: delete() 方法是 QuerySet 上的方法,但并不适用于 Manager 本身。这是一种保护机制,是为了避免意外地调用 Entry.objects.delete() 方法导致 所有的 记录被误删除。如果你确认要删除所有的对象,那么你必须显式地调用:

1
Book.objects.all().delete()  
    5、修改表记录

      方式一:

        通过修改实例对象的属性方式。注意:一定要对象.save()

1
2
3
book = models.Book.objects.get(title="吸星大法")
book.price = 180
book.save()

      方式二:

        通过ORM提供的objects提供的方法 update来实现。

1
models.Book.objects.filter(title="吸星大法").update(price=190)

        此外,update()方法对于任何结果集(QuerySet)均有效,这意味着你可以同时更新多条记录update()方法会返回一个整型数值,表示受影响的记录条数。 

     

一:  html 模板继承

        模板继承主要使用在几个界面大体类似 只是 地方做修改的时候的操作

        1:首先先建立一个公共模板

        

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/bootstrap/css/bootstrap.css">
 7     <link rel="stylesheet" href="/static/css/dsb.css">
 8     {% block css %}
 9     {% endblock css %}
10 </head>
11 <body>
12 
13     <nav class="navbar navbar-inverse navbar-fixed-top">
14       <div class="container-fluid">
15         <div class="navbar-header">
16           <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
17             <span class="sr-only">Toggle navigation</span>
18             <span class="icon-bar"></span>
19             <span class="icon-bar"></span>
20             <span class="icon-bar"></span>
21           </button>
22           <a class="navbar-brand" href="#">图书管理系统</a>
23         </div>
24         <div id="navbar" class="navbar-collapse collapse">
25           <ul class="nav navbar-nav navbar-right">
26             <li><a href="#">Dashboard</a></li>
27             <li><a href="#">Settings</a></li>
28             <li><a href="#">Profile</a></li>
29             <li><a href="#">Help</a></li>
30           </ul>
31           <form class="navbar-form navbar-right">
32             <input type="text" class="form-control" placeholder="Search...">
33           </form>
34         </div>
35       </div>
36     </nav>
37 
38     <div class="container-fluid">
39       <div class="row">
40         <div class="col-sm-3 col-md-2 sidebar">
41           <ul class="nav nav-sidebar">
42             <li class="active"><a href="{% url 'book_list' %}">书籍列表 <span class="sr-only">(current)</span></a></li>
43             <li><a href="#">Reports</a></li>
44             <li><a href="#">Analytics</a></li>
45             <li><a href="#">Export</a></li>
46           </ul>
47         </div>
48         <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
49           <div class="panel panel-primary">
50       <div class="panel-heading">
51         {% block title %}
52         {% endblock title %}
53       </div>
54       <div class="panel-body">
55 
56           {% block content %}
57                 <a class="btn btn-primary" href="{% url 'add_book' %}">新增书籍</a>
58           {% endblock content %}
59       </div>
60     </div>
61         </div>
62       </div>
63     </div>
64 
65 
66 
67 </body>
68 {% block js %}
69 {% endblock js %}
70 </html>
View Code

 css 模板继承

 html 继承

 

 js 继承:

前面是在模板层定义大体框架,之后设计具体的内容

  

{% extends 'layout.html' %}

{% block title %}
<h3 class="panel-title">书籍列表</h3>
{% endblock title %}

{% block content %}
    {{ block.super }}
<table class="table table-hover">
            <thead>
        <tr>
            <th>序号</th>
            <th>id</th>
            <th>书名</th>
            <th>价格</th>
            <th>出版社</th>
            <th>出版日期</th>
            <th>操作</th>
        </tr>
    </thead>
    <tbody>
        {% for book in all_book %}
        <tr>
            <td>{{ forloop.counter }}</td>
            <td>{{ book.pk }}</td>
            <td>{{ book.title }}</td>
            <td>{{ book.price }}</td>
            <td>{{ book.publish }}</td>
            <td>{{ book.pub_date|date:"Y-m-d" }}</td>
            <td>
                <a class="btn btn-info btn-sm" href="{% url 'edit_book' book_id=book.nid %}">编辑</a>
                |
                <a class="btn btn-danger btn-sm" href="{% url 'del_book' book.nid %}">删除</a>
            </td>
        </tr>
        {% endfor %}
    </tbody>
        </table>
{% endblock content %}

      二:  ORM 多表链接

    1:创建模型

      >1: 创建图书管理系统的模型

    1.1分析:  

由 上可知 :  

  模型创建以后有5个表  

    其中  book 中的 book_id 与 book_author 是一对多的关系 ,即一本书可能会有好几个作者

    publish 表中的id 与book 表中的publish 是一对多的关系 ,即一个出版社可能会有好几个书

     author表与book_author  是一对多的关系 ,即一个作者可能会有好几个书,

    所以book_author 是多对多关系. 是第第三方表.

通过上面分析.:  Django 中可以创建4个模型. 即可实现5个表的关系

  book 模型

from django.db import models


# Create your models here.
class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    pub_date = models.DateField
    publish = models.ForeignKey("Publish", on_delete=models.CASCADE)  # 一对多
    authors = models.ManyToManyField("Author")  # 多对多
View Code

    publish 模型

class Publish(models.Model):
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=64)
    email = models.EmailField()
View Code

  author 模型

class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    au_detail = models.OneToOneField("AuthorDeail", on_delete=models.CASCADE)  # 一对一
View Code

  AuthorDeail 模型

class AuthorDeail(models.Model):
    tel = models.CharField(max_length=32)
    addr = models.CharField(max_length=255)
    birthday =models.DateField()
View Code

创建一对多关系时  对应的id Django 会自动帮填写id

 

整理 : 首先是普通方法

    正向:调用字段名  ,反向: 调用小写的表明 

    1:一对多

    正向: (在model 内写关系的为正向)

代码:

# book_obj=models.Book.objects.filter(pk=1).first()
    # print(book_obj.publish.city)

  反向:

# pub_obj =models.Publish.objects.filter(id=2).first()
    # print(pub_obj.book_set.all(),type(pub_obj.book_set.all()))
    # for i in pub_obj.book_set.all():
    #     print(i.title)

   2:多对多

  正向:

 

    # book_obj =models.Book.objects.filter(id=2).first()
    # for i in book_obj.authors.all():
    #     print(i.name,i.au_detail.tel)

   反向:

  # au_obj =models.Author.objects.filter(id=3).first()
    # for j in au_obj.book_set.all():
    #     print(j.title)

3:一对一

一对一没有正反向, 两端一样

   # 一对一查询
    # au_obj = models.Author.objects.filter(id=3).first()
    # print(au_obj.au_detail.tel)
    # au_addr = models.AuthorDetail.objects.filter(id=2).first()
    # print(au_addr.author.name)

 双下 方法的使用

  正向: 直接调用他对应的内容的字段

  反向: 反向找到其父级,调用其对应内容的字段

  

关联管理器(RelatedManager)

 

一、class RelatedManager

  "关联管理器"是在一对多或者多对多的关联上下文中使用的管理器。它存在于下面两种情况:

  1、一对多

    ForeignKey关系的“另一边”。像这样:

1
2
3
4
5
6
7
from django.db import models
  
class Publish(models.Model):
    pass
  
class Book(models.Model):
    publish = models.ForeignKey("Publish", on_delete=models.CASCADE)

    在上面的例子中,管理器publish_obj.book_set  会拥有下面介绍的方法。

  2、多对多

    ManyToManyField关系的两边:

1
2
3
4
5
6
class Author(models.Model):
    pass
 
 
class Book(models.Model):
    authors = models.ManyToManyField("Author")

    在这个例子中,book_obj.authors 和author_obj.book_set 都拥有下面的方法。

  3、方法合集

    1、add(obj1[, obj2, ...])
复制代码
把指定的模型对象添加到关联对象集中。

例如:

>>> author_obj = Author.objects.get(id=1)
>>> book_obj = Book.objects.get(id=2)
>>> author_obj .book_set.add(e) 
在上面的例子中,对于ForeignKey关系,book_obj.save()由关联管理器调用,执行更新操作。然而,在多对多关系中使用add()并不会调用任何 save()方法,而是由QuerySet.bulk_create()创建关系。

延伸:

# 1 *[]的使用
>>> book_obj = Book.objects.get(id=1)
>>> author_list = Author.objects.filter(id__gt=2)
>>> book_obj.authors.add(*author_list)


# 2 直接绑定主键
book_obj.authors.add(*[1,3])  # 将id=1和id=3的作者对象添加到这本书的作者集合中
                              # 应用: 添加或者编辑时,提交作者信息时可以用到.
复制代码
    2、create(**kwargs)
复制代码
创建一个新的对象,保存对象,并将它添加到关联对象集之中。返回新创建的对象:

>>> 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中。
复制代码
    3、remove(obj1[, obj2, ...])
复制代码
从关联对象集中移除执行的模型对象:

>>> author_obj = Author.objects.get(id=1)
>>> book_obj = Book.objects.get(id=2)
>>> author_obj .book_set.remove(book_obj) 
对于ForeignKey对象,这个方法仅在null=True时存在。
复制代码
    4、clear()
复制代码
从关联对象集中移除一切对象。

>>> author_obj = Author.objects.get(id=1)
>>> author_obj.book_set.clear()
注意这样不会删除对象 —— 只会删除他们之间的关联。

就像 remove() 方法一样,clear()只能在 null=True的ForeignKey上被调用。
复制代码
    5、set()方法

    先清空,在设置,编辑书籍时即可用到。

book = models.Book.objects.filter(title="独孤九剑").first()
book.authors.set([1, 3])  

注意:

对于所有类型的关联字段,add()、create()、remove()和clear(),set()都会马上更新数据库。换句话说,在关联的任何一端,都不需要再调用save()方法。

二、操作表记录

  1、添加一些简单的数据

    1、publish表:

    2、author表:

    3、authordatail表:

  2、一对多

复制代码
# 方式一 传对象的形式
pub_obj = models.Publish.objects.get(pk=1)
book = models.Book.objects.create(title="独孤九剑", price=180, pub_date="2018-10-23", publish=pub_obj)

# 方式二 传对象id的形式
book = models.Book.objects.create(title="独孤九剑", price=180, pub_date="2018-10-23", publish_id=1)
复制代码

    核心:明白book.publish 和 book.publish_id 的区别?

  3、多对多

复制代码
# 方式一 传对象的形式
book = models.Book.objects.filter(title="独孤九剑").first()
ling = models.Author.objects.filter(name="令狐冲").first()
ying = models.Author.objects.filter(name="任盈盈").first()
book.authors.add(ling, ying)

# 方式二 传对象id的形式
book = models.Book.objects.filter(title="独孤九剑").first()
ling = models.Author.objects.filter(name='令狐冲').first()
ying = models.Author.objects.filter(name='任盈盈').first()
book.authors.add(ling.pk, ying.pk)
复制代码

    核心:book.authors.all()是什么?

    多对多其他常用API:

1
2
3
book_obj.authors.remove()      # 将某个特定的对象从被关联对象集合中去除。    ======   book_obj.authors.remove(*[])
book_obj.authors.clear()       #清空被关联对象集合
book_obj.authors.set()         #先清空再设置

  more

  2、基于对象的跨表查询

    1、一对多查询(Publish 与 Book)

    正向查询(按字段 publish)

1
2
3
4
# 查询主键为1的书籍的出版社所在的城市
book_obj=Book.objects.filter(pk=1).first()
# book_obj.publish 是主键为1的书籍对象关联的出版社对象
print(book_obj.publish.city)

    反向查询(按book表)

1
2
3
4
5
6
# 查询明教出版社出版的书籍名
publish=Publish.objects.get(name="明教出版社")
#publish.book_set.all() : 与明教出版社关联的所有书籍对象集合
book_list=publish.book_set.all()   
for book_obj in book_list:
       print(book_obj.title)
    2、一对一查询(Author 和 AuthorDetail)

    正向查询(按字段:au_detail):

1
2
# 查询令狐冲的电话<br>ling=Author.objects.filter(name="令狐冲").first()
print(ling.au_detail.tel)

    反向查询(按表名:author):

1
2
3
4
5
# 查询所有住址在黑木崖的作者的姓名
  
authorDetail_list=AuthorDetail.objects.filter(addr="黑木崖")
for obj in authorDetail_list:
     print(obj.author.name)
    3、多对多查询 (Author 与 Book)

    正向查询(按字段:authors):

1
2
3
4
5
6
# 独孤九剑所有作者的名字以及手机号
 
book_obj = Book.objects.filter(title="独孤九剑").first()
authors = book_obj.authors.all()
for author_obj in authors:
    print(author_obj.name, author_obj.au_detail.tel)

    反向查询(按表名:book_set):

1
2
3
4
5
6
# 查询令狐冲出过的所有书籍的名字
 
    author_obj=Author.objects.get(name="令狐冲")
    book_list=author_obj.book_set.all()        #与令狐冲作者相关的所有书籍
    for book_obj in book_list:
        print(book_obj.title)

    注意:

      你可以通过在 ForeignKey() 和ManyToManyField的定义中设置 related_name 的值来覆写 FOO_set 的名称。例如,如果 Book model 中做一下更改:

1
publish = models.ForeignKey("Publish", on_delete=models.CASCADE, related_name="book_list")

    那么接下来就会如我们看到这般:

1
2
3
4
# 查询 明教出版社出版过的所有书籍
 
publish=Publish.objects.get(name="明教出版社")
book_list=publish.book_list.all()  # 与明教出版社关联的所有书籍对象集合

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

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

'''
    正向查询按字段,反向查询按表名小写用来告诉ORM引擎join哪张表
'''
    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、多对多查询 
复制代码
# 练习: 查询令狐冲出过的所有书籍的名字(多对多)

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

    # 反向查询 按表名:book
    queryResult=Author.objects.filter(name="令狐冲").values_list("book__title","book__price")
复制代码
    3、一对一查询
复制代码
# 查询令狐冲的手机号
    
    # 正向查询
    ret=Author.objects.filter(name="令狐冲").values("au_detail__tel") 

  #
反向查询
  ret=AuthorDetail.objects.filter(author__name="令狐冲").values("tel")
复制代码
    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")


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

# 方式1: queryResult=Book.objects.filter(authors__au_detail__tel__startswith="132").values_list("title","publish__name")

   # 方式2:
   ret=Author.objects.filter(au_detail__tel__startswith="132").values("book__title","book__publish__name")
复制代码

二、操作表记录

  1、添加一些简单的数据

    1、publish表:

    2、author表:

    3、authordatail表:

  2、一对多

复制代码
# 方式一 传对象的形式
pub_obj = models.Publish.objects.get(pk=1)
book = models.Book.objects.create(title="独孤九剑", price=180, pub_date="2018-10-23", publish=pub_obj)

# 方式二 传对象id的形式
book = models.Book.objects.create(title="独孤九剑", price=180, pub_date="2018-10-23", publish_id=1)
复制代码

    核心:明白book.publish 和 book.publish_id 的区别?

  3、多对多

复制代码
# 方式一 传对象的形式
book = models.Book.objects.filter(title="独孤九剑").first()
ling = models.Author.objects.filter(name="令狐冲").first()
ying = models.Author.objects.filter(name="任盈盈").first()
book.authors.add(ling, ying)

# 方式二 传对象id的形式
book = models.Book.objects.filter(title="独孤九剑").first()
ling = models.Author.objects.filter(name='令狐冲').first()
ying = models.Author.objects.filter(name='任盈盈').first()
book.authors.add(ling.pk, ying.pk)
复制代码

    核心:book.authors.all()是什么?

    多对多其他常用API:

1
2
3
book_obj.authors.remove()      # 将某个特定的对象从被关联对象集合中去除。    ======   book_obj.authors.remove(*[])
book_obj.authors.clear()       #清空被关联对象集合
book_obj.authors.set()         #先清空再设置

  more

  2、基于对象的跨表查询

    1、一对多查询(Publish 与 Book)

    正向查询(按字段 publish)

1
2
3
4
# 查询主键为1的书籍的出版社所在的城市
book_obj=Book.objects.filter(pk=1).first()
# book_obj.publish 是主键为1的书籍对象关联的出版社对象
print(book_obj.publish.city)

    反向查询(按book表)

1
2
3
4
5
6
# 查询明教出版社出版的书籍名
publish=Publish.objects.get(name="明教出版社")
#publish.book_set.all() : 与明教出版社关联的所有书籍对象集合
book_list=publish.book_set.all()   
for book_obj in book_list:
       print(book_obj.title)
    2、一对一查询(Author 和 AuthorDetail)

    正向查询(按字段:au_detail):

1
2
# 查询令狐冲的电话<br>ling=Author.objects.filter(name="令狐冲").first()
print(ling.au_detail.tel)

    反向查询(按表名:author):

1
2
3
4
5
# 查询所有住址在黑木崖的作者的姓名
  
authorDetail_list=AuthorDetail.objects.filter(addr="黑木崖")
for obj in authorDetail_list:
     print(obj.author.name)
    3、多对多查询 (Author 与 Book)

    正向查询(按字段:authors):

1
2
3
4
5
6
# 独孤九剑所有作者的名字以及手机号
 
book_obj = Book.objects.filter(title="独孤九剑").first()
authors = book_obj.authors.all()
for author_obj in authors:
    print(author_obj.name, author_obj.au_detail.tel)

    反向查询(按表名:book_set):

1
2
3
4
5
6
# 查询令狐冲出过的所有书籍的名字
 
    author_obj=Author.objects.get(name="令狐冲")
    book_list=author_obj.book_set.all()        #与令狐冲作者相关的所有书籍
    for book_obj in book_list:
        print(book_obj.title)

    注意:

      你可以通过在 ForeignKey() 和ManyToManyField的定义中设置 related_name 的值来覆写 FOO_set 的名称。例如,如果 Book model 中做一下更改:

1
publish = models.ForeignKey("Publish", on_delete=models.CASCADE, related_name="book_list")

    那么接下来就会如我们看到这般:

1
2
3
4
# 查询 明教出版社出版过的所有书籍
 
publish=Publish.objects.get(name="明教出版社")
book_list=publish.book_list.all()  # 与明教出版社关联的所有书籍对象集合

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

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

'''
    正向查询按字段,反向查询按表名小写用来告诉ORM引擎join哪张表
'''
    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、多对多查询 
复制代码
# 练习: 查询令狐冲出过的所有书籍的名字(多对多)

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

    # 反向查询 按表名:book
    queryResult=Author.objects.filter(name="令狐冲").values_list("book__title","book__price")
复制代码
    3、一对一查询
复制代码
# 查询令狐冲的手机号
    
    # 正向查询
    ret=Author.objects.filter(name="令狐冲").values("au_detail__tel") 

  #
反向查询
  ret=AuthorDetail.objects.filter(author__name="令狐冲").values("tel")
复制代码
    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")


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

# 方式1: queryResult=Book.objects.filter(authors__au_detail__tel__startswith="132").values_list("title","publish__name")

   # 方式2:
   ret=Author.objects.filter(au_detail__tel__startswith="132").values("book__title","book__publish__name")
复制代码
# book_obj =models.Book.objects.filter(id=2).first()
# for i in book_obj.authors.all():
# print(i.name,i.au_detail.tel)



  '''1、查询丐帮出版社出版的所有书名和作者名称;
    2、查询独孤九剑的作者名称和出版社名称;
    3、查询吸星大法的作者的姓名、电话和地址;
    4、查询令狐冲写的书籍,在哪些出版社出版过,获取其出版社名称和地址;
    5、查询出版社地址为黑木崖,在该出版社出版过书籍的作者姓名和邮箱;
   '''
    # 正向查询按字段, 反向查询按小写表名。
    # 1方式1 正向 双下
    # books1 =models.Book.objects.filter(publish__id=2).values("title","authors__name")
    # print(books1)
    # print(">>>>>>>>>>>>>>>>>")
    # # 1方式2 反向 双下
    # books2 =models.Publish.objects.filter(id=2).values("book__title","book__authors__name")
    # print(books2)
    # # 1 方式3 反向
    # pub1 =models.Publish.objects.filter(id=2).first()
    # for i in pub1.book_set.all():
    #     for j in i.authors.all():
    #
    #         print(i.title,j.name)


    # 2 方法1
    # books1 =models.Book.objects.filter(id=2).values("authors__name","publish__name")
    # print(books1)
    # #2 方法2
    # books2 =models.Author.objects.filter(book__id=2).values("name","book__publish__name")
    # print(books2)
    # #2 方法3
    # books3 =models.Book.objects.filter(id=2)

    # for i in books3:
    #     name,pub=i.authors.all(),i.publish.name
    #     for j in name:
    #         print(j.name,i.publish)
    # 3、查询吸星大法的作者的姓名、电话和地址;

    # 3 方法1:
    # books1=models.Book.objects.filter(id=3).values("authors__name","authors__au_detail__tel","authors__au_detail__addr")
    #
    # print(books1)
    # #3 方法2:
    # books2 =models.Author.objects.filter(book__id=3).values("name","au_detail__tel","au_detail__addr")
    # print(books2)
    # # 3 方法3:
    # books3 =models.Book.objects.filter(id=3).first().authors.all()
    # for i in books3:
    #     print(i.name,i.au_detail.tel,i.au_detail.addr)
    # 4、查询令狐冲写的书籍,在哪些出版社出版过,获取其出版社名称和地址;
    # 4 方法1:
    # books1 =models.Author.objects.filter(id=3).values("book__title","book__publish__name","book__publish__city")
    # print(books1)
    # # 4 方法2:
    # books2 =models.Book.objects.filter(authors__id=3).values("title","publish__name","publish__city")
    # print(books2)
    # #4 方法3 :
    # books3 =models.Author.objects.filter(id=3).first()
    # for i in books3.book_set.all():
    #     print(i.title,i.publish.name,i.publish.city)
    #
    # 5     5、查询出版社地址为黑木崖,在该出版社出版过书籍的作者姓名和邮箱;
    # 5 方法1 :
    books1 =models.Publish.objects.filter(id=2).values("book__title","book__authors__name","book__authors__au_detail__addr")
    print(books1)
    # 5 方法2:
    books2 =models.Book.objects.filter(publish_id=2).values("title","authors__name","authors__au_detail__addr")
    print(books2)
    # 5 方法3:
    books3 =models.Publish.objects.filter(id=2).first()
    for i in books3.book_set.all():
        for j in i.authors.all():
            print(i.title,j.name)


 
原文地址:https://www.cnblogs.com/baili-luoyun/p/10555216.html