多表查询

多表查询

多表查询又分为:

  1. 子查询
  2. 连表查询

一对多字段增删改查:

一对多字段增删改查
    models.Book.objects.create(title='三国演义',price=123.23,publish_id=1)  # publish_id直接传出版社主键值

    publish_obj = models.Publish.objects.filter(pk=2).first()
    models.Book.objects.create(title='水浒传',price=123.23,publish=publish_obj)  # publish直接传出版社数据对象

    查
    book_obj = models.Book.objects.filter(pk=1).first()
    print(book_obj.publish)  # 获取到当前所对应的出版社对象
    print(book_obj.publish_id)  # 获取到的就是表中的实际字段

    改
    models.Book.objects.filter(pk=1).update(publish_id=3)
    publish_obj = models.Publish.objects.filter(pk=2).first()
    models.Book.objects.filter(pk=1).update(publish=publish_obj)

    删除
    models.Publish.objects.filter(pk=2).delete()
    默认也是级联更新 级联删除

多对多字段的增删改查:

 给主键为3的书籍添加两个作者 1 2
    book_obj = models.Book.objects.filter(pk=3).first()
    print(book_obj.authors)  # 就相当于 已经在书籍和作者的关系表了
    book_obj.authors.add(1)
    book_obj.authors.add(2,3)
    author_obj = models.Author.objects.filter(pk=1).first()
    author_obj1 = models.Author.objects.filter(pk=2).first()
    book_obj.authors.add(author_obj)
    book_obj.authors.add(author_obj,author_obj1)
    """
    add() 括号内既可以传数字也可以传数据对象
    并且都支持传多个
    """
    修改关系
    book_obj = models.Book.objects.filter(pk=3).first()
    book_obj.authors.set([3,])
    book_obj.authors.set([1,3])
    author_obj = models.Author.objects.filter(pk=1).first()
    author_obj1 = models.Author.objects.filter(pk=2).first()
    book_obj.authors.set((author_obj,))
    book_obj.authors.set((author_obj,author_obj1))
    """
    set() 括号内 既可以传数字也传对象 
    并且也是支持传多个的
    但是需要注意 括号内必须是一个可迭代对象
    """

    删
    book_obj = models.Book.objects.filter(pk=3).first()
    book_obj.authors.remove(2)
    book_obj.authors.remove(1,2)

    author_obj = models.Author.objects.filter(pk=1).first()
    author_obj1 = models.Author.objects.filter(pk=2).first()
    book_obj.authors.remove(author_obj)
    book_obj.authors.remove(author_obj,author_obj1)
    """
    remove() 括号内 既可以传数字也传对象 
    并且也是支持传多个的
    """
    清空
    book_obj = models.Book.objects.filter(pk=3).first()
    book_obj.authors.clear()
    """clear()括号内不需要传任何参数 直接清空当前书籍对象所有的记录"""


    """
ORM跨表查询
        1.子查询
        2.连表查询
        
    正反向的概念
        外键字段在谁那儿 由谁查谁就是正向
        
        谁手里有外键字段 谁就是正向查
        没有外键字段的就是反向
        书籍对象 查  出版社    外键字段在书籍       正向查询
        出版社 查 书籍         外键字段在书籍       反向查询
        
        
        正向查询按字段
        反向查询按表名小写 ...
        
    """

简而言之,就是我手里有主键字段,要去查你,就是正向查询,你来查我,就是反向查询。

 """
    正向查询 按字段 
    当该字段所对应的数据有多个的时候 需要加.all()
    否者点外键字段直接就能够拿到数据对象
    """
1.基于对象的跨表查询    子查询
    1.查询书籍是python入门的出版社名称
    book_obj = models.Book.objects.filter(title='python入门').first()
    # 正向查询按字段
    print(book_obj.publish.name)
    print(book_obj.publish.addr)
    2.查询书籍主键是6的作者姓名
    book_obj = models.Book.objects.filter(pk=6).first()
    # print(book_obj.authors)  # app01.Author.None
    print(book_obj.authors.all())
    3.查询作者是jason的手机号
    author_obj = models.Author.objects.filter(name='jason').first()
    print(author_obj.author_detail.phone)
    print(author_obj.author_detail.addr)
   



 """
    反向查询按表名小写 
        什么时候需要加_set
            当查询的结果可以是多个的情况下 需要加_set.all()
            无论你的查询结果有几个,只要他存在多个的情况,就要加
        什么时候不需要加_set
            当查询的结果有且只有一个的情况下 不需要加任何东西 直接表名小写即可
    """
    4.查询出版社是东方出版社出版过的书籍
    publish_obj = models.Publish.objects.filter(name='东方出版社').first()
    # print(publish_obj.book_set)  # app01.Book.None
    print(publish_obj.book_set.all())
    5.查询作者是jason写过的所有的书
    author_obj = models.Author.objects.filter(name='jason').first()
    # print(author_obj.book_set)  # app01.Book.None
    print(author_obj.book_set.all())
    6.查询手机号是110的作者
    author_detail_obj = models.AuthorDetail.objects.filter(phone=110).first()
    print(author_detail_obj.author)
    print(author_detail_obj.author.name)
    print(author_detail_obj.author.age)
   

基于双下划线的跨表查询 连表查询

1.查询书籍是python入门的出版社名称
    正向
    res = models.Book.objects.filter(title='python入门').values('publish__name')
    print(res)
    反向 (这才是真正的反向查询,要什么就应该在什么表里查)
    res = models.Publish.objects.filter(book__title='python入门').values('name')
    print(res)


    2.查询作者是jason的手机号码
    正向
    res1 = models.Author.objects.filter(name='jason').values('author_detail__phone')
    print(res1)
    反向
    res = models.AuthorDetail.objects.filter(author__name='jason').values('phone','author__age')
    print(res)



    3.查询手机号是120的作者姓名

    res2 = models.AuthorDetail.objects.filter(phone=120).values('author__name')
    print(res2)
    res = models.Author.objects.filter(author_detail__phone=120).values('name','author_detail__addr')
    print(res)


    4.查询出版社是东方出版社出版的书籍名称
    res = models.Publish.objects.filter(name='东方出版社').values('book__title','addr')
    print(res)
    5.查询作者是jason的写过的书的名字和价格
    res = models.Author.objects.filter(name='jason').values('book__title','book__price')
    print(res)

    7.查询书籍是python入门的作者的手机号
    res = models.Book.objects.filter(title='python入门').values('authors__author_detail__phone')
    print(res)

解释一下上面的第七题,也就是最后一题。

我们要查询的是作者的手机号,在Book表里面没有这个字段,而且Book表也没法直接和作者详情表有联系,所以要通过中间的一张表也就是作者表,首先查询书籍名称是python入门的书,然后通过values来取字段的值,书籍查找作者是正向查询,所以直接通过字段名来查询就好了,这里括号中写出 authors 的时候,已经跨到作者表了(因为authors是外键字段),然后双下划綫 author_detail,就跨到了作者详情表,然后在通过双下滑想取到了phone的值。

也就是说:

只要表与表之间有外键的联系,可以通过无限的双下划綫跨越无数张表去查询数据

讲了这么多,简单的总结一下。

正向查询:也就是外键在我这边,我查找你,直接像这样就可以了

查询名叫python入门的书的出版社
book_obj = models.Book.objects.filter(title='python入门').first()
#也可以写成 book_obj = models.Book.objects.filter(title='python入门').values(publish__name)
    # 正向查询按字段
    print(book_obj.publish) #publish是外键,直接就可以拿到这个publish对象。
    print(book_obj.publish.addr)#可以直接就点出属性了

方向查询:外键在你那边,我查找你,原本写法如下

查询出版社是东方出版社出版过的书籍
publish_obj = models.Publish.objects.filter(name='东方出版社').first()
	print(publish_obj.book_set.all())#外键在对面,你就是一的那一边,查找结果一定是可以存在多个的,所以加_set就好了

后来学了双下划綫,就如下了

查询名叫python入门的书的出版社名称
res=models.Book.objects.filter(publish__name='东方出版社').values('title')
#因为是反向查询,所以只用写表的名字的小写就可以了,写了publish之后就相当于跨表到了publish表,双下划綫就拿到了name。
posted @ 2019-10-27 16:53  chanyuli  阅读(163)  评论(0编辑  收藏  举报