• 7 多表操作


    一、多表之间的关系

     1 一对一:
     2 1️⃣ 必须对先被关联表添加记录(即没有外键的表)
     3 2️⃣ 关联表中的关联字段可以直接使用被关联表时的对象
     4 创建关联表时,可直接使用外键 id 传入被关联表中未被绑定的元素
     5 
     6 一对多:
     7 1️⃣ 必须对先被关联表添加记录(即没有外键的表)
     8 2️⃣ 关联表中的关联字段可以直接使用被关联表时的对象
     9 3️⃣ 过滤出被关联表的对象记得加上 first() 处理
    10 4️⃣ 让关联表 id = 被关联表 id
    11 
    12 多对多:
    13 1️⃣ 添加关联关系使用 book.authors.add(1,2),表示的是往中间表插入记录,没有返回值
    14 book:表示的是对应的 book 某本书,而不是在创建表时的 authors 属性
    15 1,2:表示的是 authors.id
    16 2️⃣ book.authors.add(*(1,2))
    17 3️⃣ add(参数1,参数2) # 参数可以直接传对象,以逗号分隔

    1 解除绑定关系

    remove() # 需要传参数,参数即需要解除的 id 或者对象,可以是多个,用逗号分隔;也可用解压的方式(*(参数1,参数2))

    2 一次性清空绑定关系

    clear()  # 不用传参数

    3 先清空再设置

    set()  # 底层原理是先清空,然后再使用  add() 函数来添加;参数必须是可迭代对象

    二、多表查询的总结

    authordetail = AuthorDetail.objects.filter(pk=zhf.authordetail_id)
    print(zhf.authordetail)
    
    # 这种情况下会查询两次,第一次是 authordetail 这个表中查询一次;第二次是 zhf.authordetail 执行查询一次
    Notice

    1 正向查询与反向查询

    正向查询:关联字段在 A 表中,查询表 B,按字段来查询,即 A.B.字段名
    
    反向查询:关联字段在 A 表中,由表 B 查询 表 A,按照 表名小写_set 方式来查询
    如:B.a_set.all()
    B.a_set 是 Manage 对象
    B.a_set.all() 是 QuerySet 对象

    2 正向查询方式与反向查询方式

    总结 正向查询 反向查询
    one to one 按照字段 表名小写
    one to many 按照字段 表名小写_set
    many to many 按照字段 表名小写_set

    三、基于双下划线的多表查询(链表查询)

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

      正向查询按字段,反向查询按表名小写用来告诉ORM引擎join哪张表

    1 在使用 __ 双下划线告诉 ORM 该 JOIN 哪张表前提下的总结

    总结 正向查询 反向查询
    one to one 按照字段 表名小写
    one to many 按照字段 表名小写
    many to many 按照字段 表名小写

    四、聚合函数

    form django.db.models.import Avg,Count,Max,Min,Sum
    # 使用 aggregate() 函数表示聚合函数
    
    Book.objects.all.aggregate(Avg('price'))  # 返回值是一个字典,可传多个参数
    # 给字段重命名
    Book.objects.all.aggregate(avg_price=Avg('price')) 

    五、分组

    annotate() 为调用的 QuerySet 中每一个对象都生成一个独立的统计值(统计方法用聚合函数)。

    from django.db.models import Avg, Max, Sum, Min, Max, Count
    book_list = models.Book.objects.all().annotate(author_num=Count("authors"))
    for book in book_list:
         print(book.name)
         print(book.author_num)
    book_list = models.Book.objects.all().annotate(author_num=Count("authors")).values('name','author_num')
    print(book_list)

    总结 :跨表分组查询本质就是将关联表 JOIN 成一张表,再按单表的思路进行分组查询。 

    1️⃣ value 在 annotate 前,表示group by 字段;在 annotate 后,表示要 select 的字段(若不写 value,默认是以基表的主键为基准)
    2️⃣ filter 在 annotate 前,指的是 where 的东西;在 annotate 后面指的是 having 的东西
    Notice

    六、F 查询和 Q 查询

    1 F 查询

      Django 提供 F() 函数。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。修改操作也可以使用F函数。

    from django.db.models import F,Q
    #评论数大于阅读数的所有书,返回的是 QuerySet 对象
    Book.objects.all().filter(commit_num__gt=F('read_num'))
    
    # 对所有的书价格 +1
    Book.objects.all().update(price=F('price')+1)

    2 Q 查询

      filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 若需要执行更复杂的查询(例如 OR 语句),可以使用 Q 对象

      Q 对象可以使用 & 和 | 操作符组合起来。当一个操作符在两个 Q 对象上使用时,它产生一个新的 Q 对象。

    bookList=Book.objects.filter(Q(authors__name="888")|Q(authors__name="666"))

    # 等同于 SQL 语句
    WHERE name ="yuan" OR name ="egon"
    如果出现Q 对象,它必须位于所有关键字参数的前面
    bookList=Book.objects.filter(Q(publish_Date__year=9999) | Q(publish_Date__year=8888), name__icontains="Django")
    Notice
  • 相关阅读:
    Coursera 高级数据结构与算法,北京大学
    heap 算法函数
    笛卡尔树 Cartesian tree
    POJ 1830 开关问题 异或高斯消元
    jmeterJSR223取样器和断言
    Flask JinJa2模板语法测试
    Python Flask Web 试题汇编<待续>
    jsDoc自动生成文档
    SQL 优化
    IO多路复用之select、poll、epoll的区别
  • 原文地址:https://www.cnblogs.com/Smart1san/p/9657925.html
Copyright © 2020-2023  润新知