• 11.16 知识总结(模型层更多内容)


    一、 多表查询(跨表查询)


    子查询:分步查询
    链表查询:把多个有关系的表拼接成一个大表(虚拟表)
        inner join 
        left join
        right join

     1.1 基于双下划线的查询

    1. # 1 年龄大于35岁的数据
    2. res = models.User.objects.filter(age__gt=35)
    3. print(res)
    4. 2 年龄小于35岁的数据
    5. res = models.User.objects.filter(age__lt=35)
    6. print(res)
    7. 大于等于 小于等于
    8. res = models.User.objects.filter(age__gte=32)
    9. print(res)
    10. res = models.User.objects.filter(age__lte=32)
    11. print(res)
    12. 年龄是18 或者 32 或者40
    13. res = models.User.objects.filter(age__in=[18,32,40])
    14. print(res)
    15. 年龄在1840岁之间的 首尾都要
    16. res = models.User.objects.filter(age__range=[18,40])
    17. print(res)
    18. 查询出名字里面含有s的数据 模糊查询
    19. res = models.User.objects.filter(name__contains='s')
    20. print(res)
    21. 是否区分大小写 查询出名字里面含有p的数据 区分大小写
    22. res = models.User.objects.filter(name__contains='p')
    23. print(res)
    24. 忽略大小写
    25. res = models.User.objects.filter(name__icontains='p')
    26. print(res)
    27. res = models.User.objects.filter(name__startswith='j')
    28. res1 = models.User.objects.filter(name__endswith='j')
    29. print(res,res1)
    30. 查询出注册时间是 2020 1
    31. res = models.User.objects.filter(register_time__month='1')
    32. res = models.User.objects.filter(register_time__year='2020')

    12 多表查询前期表准备

    1. class Book(models.Model):
    2. title = models.CharField(max_length=32)
    3. price = models.DecimalField(max_digits=8,decimal_places=2)
    4. publish_date = models.DateField(auto_now_add=True)
    5. # 一对多
    6. publish = models.ForeignKey(to='Publish')
    7. # 多对多
    8. authors = models.ManyToManyField(to='Author')
    9. class Publish(models.Model):
    10. name = models.CharField(max_length=32)
    11. addr = models.CharField(max_length=64)
    12. # varchar(254) 该字段类型不是给models看的 而是给后面我们会学到的校验性组件看的
    13. def __str__(self):
    14. return self.name
    15. class Author(models.Model):
    16. name = models.CharField(max_length=32)
    17. age = models.IntegerField()
    18. # 一对一
    19. author_detail = models.OneToOneField(to='AuthorDetail')
    20. class AuthorDetail(models.Model):
    21. phone = models.BigIntegerField() # 电话号码用BigIntegerField或者直接用CharField
    22. addr = models.CharField(max_length=64)

    1.3   一对多外键增删改查

    1. 一对多外键增删改查
    2. 1 直接写实际字段 id
    3. models.Book.objects.create(title='论语',price=899.23,publish_id=1)
    4. models.Book.objects.create(title='聊斋',price=444.23,publish_id=2)
    5. models.Book.objects.create(title='老子',price=333.66,publish_id=1)
    6. 2 虚拟字段 对象
    7. publish_obj = models.Publish.objects.filter(pk=2).first()
    8. models.Book.objects.create(title='红楼梦',price=666.23,publish=publish_obj)
    9. models.Publish.objects.filter(pk=1).delete() # 级联删除
    10. 修改
    11. models.Book.objects.filter(pk=1).update(publish_id=2)
    12. publish_obj = models.Publish.objects.filter(pk=1).first()
    13. models.Book.objects.filter(pk=1).update(publish=publish_obj)

    1.4  多对多外键增删改查

    1. 如何给书籍添加作者?
    2. book_obj = models.Book.objects.filter(pk=1).first()
    3. print(book_obj.authors) # 就类似于你已经到了第三张关系表了
    4. book_obj.authors.add(1) # 书籍id为1的书籍绑定一个主键为1 的作者
    5. book_obj.authors.add(2,3)
    6. author_obj = models.Author.objects.filter(pk=1).first()
    7. author_obj1 = models.Author.objects.filter(pk=2).first()
    8. author_obj2 = models.Author.objects.filter(pk=3).first()
    9. book_obj.authors.add(author_obj)
    10. book_obj.authors.add(author_obj1,author_obj2)
    11. """
    12. add给第三张关系表添加数据
    13. 括号内既可以传数字也可以传对象 并且都支持多个
    14. """
    15. book_obj.authors.remove(2)
    16. book_obj.authors.remove(1,3)
    17. author_obj = models.Author.objects.filter(pk=2).first()
    18. author_obj1 = models.Author.objects.filter(pk=3).first()
    19. book_obj.authors.remove(author_obj,author_obj1)
    20. """
    21. remove
    22. 括号内既可以传数字也可以传对象 并且都支持多个
    23. """
    24. 修改
    25. book_obj.authors.set([1,2]) # 括号内必须给一个可迭代对象
    26. book_obj.authors.set([3]) # 括号内必须给一个可迭代对象
    27. author_obj = models.Author.objects.filter(pk=2).first()
    28. author_obj1 = models.Author.objects.filter(pk=3).first()
    29. book_obj.authors.set([author_obj,author_obj1]) # 括号内必须给一个可迭代对象
    30. """
    31. set
    32. 括号内必须传一个可迭代对象,该对象内既可以数字也可以对象 并且都支持多个
    33. """
    34. # 清空
    35. # 在第三张关系表中清空某个书籍与作者的绑定关系
    36. book_obj.authors.clear()
    37. """
    38. clear
    39. 括号内不要加任何参数
    40. """

    1.5 正反向的概念 

    # 正向
    # 反向
        外键字段在我手上那么,我查你就是正向
          外键字段如果不在手上,我查你就是反向
      
      book >>>外键字段在书那儿(正向)>>> publish
      publish    >>>外键字段在书那儿(反向)>>>book
      
      一对一和多对多正反向的判断也是如此
      
    """
    正向查询按外键字段
    反向查询按表名小写
                    _set
                    ...
    """

    二、子查询(基于对象的跨表查询)

    1. # 1.查询书籍主键为1的出版社
    2. book_obj = models.Book.objects.filter(pk=1).first()
    3. # 书查出版社 正向
    4. res = book_obj.publish
    5. # print(res)
    6. print(res.name)
    7. print(res.addr)
    8. 2.查询书籍主键为2的作者
    9. book_obj = models.Book.objects.filter(pk=2).first()
    10. 书查作者 正向
    11. res = book_obj.authors # app01.Author.None
    12. res = book_obj.authors.all() # , ]>
    13. print(res)
    14. 3.查询作者jason的电话号码
    15. author_obj = models.Author.objects.filter(name='jason').first()
    16. res = author_obj.author_detail
    17. print(res)
    18. print(res.phone)
    19. print(res.addr)
    20. """
    21. 在书写orm语句的时候跟写sql语句一样的
    22. 不要企图一次性将orm语句写完 如果比较复杂 就写一点看一点
    23. 正向什么时候需要加.all()
    24. 当你的结果可能有多个的时候就需要加.all()
    25. 如果是一个则直接拿到数据对象
    26. book_obj.publish
    27. book_obj.authors.all()
    28. author_obj.author_detail
    29. """
    30. 4.查询出版社是东方出版社出版的书
    31. publish_obj = models.Publish.objects.filter(name='东方出版社').first()
    32. 出版社查书 反向
    33. res = publish_obj.book_set # app01.Book.None
    34. res = publish_obj.book_set.all()
    35. print(res)
    36. 5.查询作者是jason写过的书
    37. author_obj = models.Author.objects.filter(name='jason').first()
    38. 作者查书 反向
    39. res = author_obj.book_set # app01.Book.None
    40. res = author_obj.book_set.all()
    41. print(res)
    42. 6.查询手机号是110的作者姓名
    43. author_detail_obj = models.AuthorDetail.objects.filter(phone=110).first()
    44. res = author_detail_obj.author
    45. print(res.name)
    46. """
    47. 基于对象
    48. 反向查询的时候
    49. 当你的查询结果可以有多个的时候 就必须加_set.all()
    50. 当你的结果只有一个的时候 不需要加_set.all()
    51. 自己总结出 自己方便记忆的即可 每个人都可以不一样
    52. """

       三、 联表查询(基于双下划线的跨表查询)

    1. # 基于双下划线的跨表查询
    2. 1.查询jason的手机号和作者姓名
    3. res = models.Author.objects.filter(name='jason').values('author_detail__phone','name')
    4. print(res)
    5. 反向
    6. res = models.AuthorDetail.objects.filter(author__name='jason') # 拿作者姓名是jason的作者详情
    7. res = models.AuthorDetail.objects.filter(author__name='jason').values('phone','author__name')
    8. print(res)
    9. 2.查询书籍主键为1的出版社名称和书的名称
    10. res = models.Book.objects.filter(pk=1).values('title','publish__name')
    11. print(res)
    12. 反向
    13. res = models.Publish.objects.filter(book__id=1).values('name','book__title')
    14. print(res)
    15. 3.查询书籍主键为1的作者姓名
    16. res = models.Book.objects.filter(pk=1).values('authors__name')
    17. print(res)
    18. 反向
    19. res = models.Author.objects.filter(book__id=1).values('name')
    20. print(res)
    21. 查询书籍主键是1的作者的手机号
    22. book author authordetail
    23. res = models.Book.objects.filter(pk=1).values('authors__author_detail__phone')
    24. print(res)
    25. """
    26. 你只要掌握了正反向的概念
    27. 以及双下划线
    28. 那么你就可以无限制的跨表
    29. """

    四、  聚合查询

    常见的统计总数,计算平均值的操作,可以用聚合函数来实现,常见的聚合函数有

    1. 聚合查询通常情况下都是配合分组一起使用的
    2. 只要是跟数据库相关的模块
    3. 基本上都在django.db.models里面
    4. 如果上述没有那么应该在django.db里面
    5. """
    6. from app01 import models
    7. from django.db.models import Max,Min,Sum,Count,Avg
    8. # 1 所有书的平均价格
    9. # res = models.Book.objects.aggregate(Avg('price'))
    10. # print(res)
    11. # 2.上述方法一次性使用
    12. res = models.Book.objects.aggregate(Max('price'),Min('price'),Sum('price'),Count('pk'),Avg('price'))
    13. print(res)

    五、  分组查询

    1. MySQL分组查询都有哪些特点
    2. 分组之后默认只能获取到分组的依据 组内其他字段都无法直接获取了
    3. 严格模式
    4. ONLY_FULL_GROUP_BY
    5. set global sql_mode='ONLY_FULL_GROUP_BY'
    6. """
    7. from django.db.models import Max, Min, Sum, Count, Avg
    8. 1.统计每一本书的作者个数
    9. res = models.Book.objects.annotate() # models后面点什么 就是按什么分组
    10. res = models.Book.objects.annotate(author_num=Count('authors')).values('title','author_num')
    11. """
    12. author_num是我们自己定义的字段 用来存储统计出来的每本书对应的作者个数
    13. """
    14. res1 = models.Book.objects.annotate(author_num=Count('authors__id')).values('title','author_num')
    15. print(res,res1)
    16. """
    17. 代码没有补全 不要怕 正常写
    18. 补全给你是pycharm给你的 到后面在服务器上直接书写代码 什么补全都没有 颜色提示也没有
    19. """
    20. 2.统计每个出版社卖的最便宜的书的价格(作业:复习原生SQL语句 写出来)
    21. res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name','min_price')
    22. print(res)
    23. 3.统计不止一个作者的图书
    24. 1.先按照图书分组 求每一本书对应的作者个数
    25. 2.过滤出不止一个作者的图书
    26. res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1).values('title','author_num')
    27. """
    28. 只要你的orm语句得出的结果还是一个queryset对象
    29. 那么它就可以继续无限制的点queryset对象封装的方法
    30. """
    31. print(res)
    32. 4.查询每个作者出的书的总价格
    33. res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('name','sum_price')
    34. # print(res)
    35. """
    36. 如果我想按照指定的字段分组该如何处理呢?
    37. models.Book.objects.values('price').annotate()
    38. 后续BBS作业会使用
    39. 你们的机器上如果出现分组查询报错的情况
    40. 你需要修改数据库严格模式

     六、 F与Q查询

    3. 1 F查询

    1. 1.查询卖出数大于库存数的书籍
    2. F查询
    3. """
    4. 能够帮助你直接获取到表中某个字段对应的数据
    5. """
    6. from django.db.models import F
    7. res = models.Book.objects.filter(maichu__gt=F('kucun'))
    8. print(res)
    9. 2.将所有书籍的价格提升500
    10. models.Book.objects.update(price=F('price') + 500)
    11. 3.将所有书的名称后面加上爆款两个字
    12. """
    13. 在操作字符类型的数据的时候 F不能够直接做到字符串的拼接
    14. """
    15. from django.db.models.functions import Concat
    16. from django.db.models import Value
    17. models.Book.objects.update(title=Concat(F('title'), Value('爆款')))
    18. # models.Book.objects.update(title=F('title') + '爆款') # 所有的名称会全部变成空白

      6.2   Q查询

    Q查询
        # 1.查询卖出数大于100或者价格小于600的书籍
        # res = models.Book.objects.filter(maichu__gt=100,price__lt=600)
        """filter括号内多个参数是and关系"""
        from django.db.models import Q
        # res = models.Book.objects.filter(Q(maichu__gt=100),Q(price__lt=600))  # Q包裹逗号分割 还是and关系
        # res = models.Book.objects.filter(Q(maichu__gt=100)|Q(price__lt=600))  # | or关系
        # res = models.Book.objects.filter(~Q(maichu__gt=100)|Q(price__lt=600))  # ~ not关系
        # print(res)  #

        # Q的高阶用法  能够将查询条件的左边也变成字符串的形式
        q = Q()
        q.connector = 'or'
        q.children.append(('maichu__gt',100))
        q.children.append(('price__lt',600))
        res = models.Book.objects.filter(q)  # 默认还是and关系
        print(res)

  • 相关阅读:
    在Linux安装nginx
    java中如何让1+1=3
    极大似然法
    力扣 8. 字符串转换整数 (atoi)
    【苹果家庭推送iMessage】软件安装应用程序访问HealthKit HomeKit
    Java多态
    iwebsec靶场 文件包含漏洞通关笔记8-php://input伪协议利用
    Ubuntu 20.04安装绿联PL2303串口驱动
    java:数组缩减
    MSPG3507——蓝牙接收数据显示在OLED,滴答定时器延时500MS
  • 原文地址:https://blog.csdn.net/weixin_66010453/article/details/134442538