day08 外键字段的增删改查 正向反向插叙概念 跨表查询 聚合查询与分组查询 F查询

day08 外键字段的增删改查 正向反向插叙概念 跨表查询 聚合查询与分组查询 F查询

昨日内容复习

  • 自定义过滤器、标签、inclusion_tag

    1.首先现在应用目录下创建名字为templatetags的文件夹
    2.文件夹里创建任意名称的.py文件
    里面写两行内容
    	from django import template
    	register=template.library()
    @register.filter() 过滤器
    @register.simple_tag() 标签
    @register.inclusion_tag() inclusion_tag
    
    html页面使用需要先加载
    {%load py文件名 %}
    
    
  • 模板的继承和导入

    先在母版中利用block划定将来可以被修改的区域
    	{% block 区域名称 %}
        	母版内容
        {% endblock %}
    在子版中先继承
    	{% extends 母版名 %}
        {% block 区域名称 %}
        	子版内容
        {% endblock %}
    """
    在母版中至少应该含有三块区域
    	css、content、js
    在子版中也可以继续使用母版的内容
    	{{ block.super }}
    """
    #########################
    模板的导入其实就是将页面的某个部分当做组件的形式
    导入到其他页面的某个位置上(使用频率不高)
    	{% include 文件名称 %}
    如何创建django测试文件
    	方式1:使用pycharm自动提供的python console
        方式2:拷贝manage.py前四行内容 再加上固定的两句(任意文件)
            	import django
                django.setup()
         
    如何查看orm内部的SQL语句
    	方式1:针对结果为queryset对象可以直接点query查看
        方式2:直接在配置文件中拷贝固定的代码即可
    LOGGING = {
            'version': 1,
            'disable_existing_loggers': False,
            'handlers': {
                'console':{
                    'level':'DEBUG',
                    'class':'logging.StreamHandler',
                },
            },
            'loggers': {
                'django.db.backends': {
                    'handlers': ['console'],
                    'propagate': True,
                    'level':'DEBUG',
                },
            }
    }
    
  • 查询关键字

    """
    pk特指主键 自动查找主键名称
    """
    all()  # 查询所有
    filter()  # 类似于where筛选 括号内逗号隔开多个条件默认是and关系
    get()  # 查找具体的数据对象 条件不存在直接报错(不推荐使用)
    values()  # 结果相当于列表套字典(指定查询的字段)
    values_list()  # 结果相当于列表套元组(指定查询的字段)
    first()、last()  # 拿queryset数据集中第一个和最后一个数据
    order_by()  # 排序
    distinct()  # 去重(有主键的情况下肯定无法去重)
    exclude()  # 取反
    exists()  # 判断是否有结果 返回True或False
    
  • 神奇的双下划线

    字段名__gt=值     某个字段大于某个值的数据对象 
        字段名__gte=值     某个字段大于等于某个值的数据对象 
        
        字段名__lt=值     某个字段小于某个值的数据对象 
        字段名__lte=值     某个字段小于等于某个值的数据对象 
        
        字段名__in=['123','234']     某个字段等于值1或值2或值3 的数据对象 
        	加引号看前提 ,如果是浮点型要加引号,因为python对浮点数这块不够精确
            
        字段名__range=(200,500)    某个字段的值在200-500之间 的数据对象 
        
        字段名__contains='p'   某个字段的值包含字母'p'之间 的数据对象   区分大小写
        字段名__icontains='p'   某个字段的值包含字母'p'之间 的数据对象   不区分大小写
        
        字段名__startswith='人'   某个字段以'人'开头的数据对象
        字段名__ebdswith='的'   某个字段以'的'结束的数据对象
        
        
        #前提是日期类型
        字段名__year=2021  某个字段的年份为'2021'的数据对象
        字段名__month=11  某个字段的月为'11'的数据对象
    
    
    
    • 多表查询数据准备

      针对一对多和一对一 orm都会给字段名称后面自动加_id后缀(不要自己加)
      针对多对多字段 无需我们自己创建第三张表 写在关系表中 自动创建
      

今日内容概要

  • 外键字段的增删改查
  • 正反向查询的概念
  • 基于对象的跨表查询(子查询)
  • 基于双下划綫的跨表查询(连表操作)
  • 聚合查询与分组查询
  • F查询与Q查询

今日内容详细

  • 外键字段的增删改查

    #一对一 一对多
        #增
        #直接录入数据
        # models.Book.objects.create(title='活着',price=256.32,publish_id=1)
        #创建出版社对象录入数据 first 获取第一个数据 不加则是 一个列表套数据对象  加获取第一个位置的数据对象
        #publish可以传数据对象
        # publish_obj=models.Publish.objects.filter(pk=2).first()
        # models.Book.objects.create(title='三国义',price=123.52,publish=publish_obj)
        #改
        #直接修改
        # models.Book.objects.filter(pk=2).update(publish_id=1)
        #传入数据对象修改  先创建出版社对象  通过publis指定数据对象
        # publish_obj=models.Publish.objects.filter(pk=2).first()
        # models.Book.objects.filter(pk=1).update(publish=publish_obj)
        #删查 soeasy
    
    #多对多操作
        #增 add
        # 获取一个book对象
        # book_obj=models.Book.objects.filter(pk=3).first()
        # book_obj.authors.add(1) #操作虚拟字段相当于操作第三张表add(添加对方的id,可以写多个,因为是多对多)
        # book_obj.authors.add(1,2)
    
        #创建book对象   作者对象  通过book.虚拟字段.add(作者对象1,作者对象2)添加关系
        # book_obj = models.Book.objects.filter(pk=3).first()
        # author_obj=models.Author.objects.filter(pk=1).first()
        # author_obj1=models.Author.objects.filter(pk=2).first()
        # book_obj.authors.add(author_obj,author_obj1)
    
        """
        add
            在第三张关系表中添加数据
                括号内既可以传主键字段也可以传数据对象 并且都支持传多个
        """
        #改 set
        # book_obj=models.Book.objects.filter(pk=2).first()
        # 报错'int' object is not iterable  int对象不可迭代,可以换一个可迭代对象试一下 元组列表字典
        # book_obj.authors.set(2)  #记住指定的是虚拟字段 谁创建的谁调用
        # book_obj.authors.set([2]) #可以指定多个set([2,1])  因为是多对多
    
        #修改也可以用对象修改
        # book_obj = models.Book.objects.filter(pk=2).first()
        # 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
               在第三张关系表中修改数据
                   括号内需要传一个可迭代对象
                       可迭代对象里面的元素既可以传主键字段也可以传数据对象 并且都支持传多个
           """
    
        #删 remove
        # book_obj=models.Book.objects.filter(pk=1).first()
        # book_obj.authors.remove(1)    #记住指定的是虚拟字段 谁创建的谁调用
        # book_obj.authors.remove(1,2)     #可以指定多个参数
    
        #删除也可以用对象
        # book_obj=models.Book.objects.filter(pk=1).first()
        # 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
              在第三张关系表中删除数据
                  括号内既可以传主键字段也可以传数据对象 并且都支持传多个
        """
    
        #清空数据 clear
        # book_obj = models.Book.objects.filter(pk=2).first()
        # book_obj.authors.clear()  # 清空当前书籍与作者的所有绑定关系
        """
        clear
            在第三张关系表中清空数据
                括号内无需传值
        """
    
  • 正反向查询的概念

    正向查询
    	书籍对象查出版社对象 外键字段在书表中 一对多  # 正向查询
        书籍对象查作者对象 外键字段在书表中   多对多 # 正向查询
        作者对象查作者详情 外键字段在作者中   一对一 # 正向查询
        
    反向查询
    	出版社查书籍对象 外键字段不在出版社表中   # 反向查询
        作者查书籍对象 外键字段不在作者表中  # 反向查询
        作者详情查作者 外键字段不在作者详情表中  # 反向查询 
    """
    	查询数据的时候如果外键字段"在你的手上"则为正向查询 models.表名  看这个表名有外键字段则正向查询
    	如果外键字段不在则为反向查询
    """
    
    口诀:
        正向查询按外键字段 ...
        反向查询按表名小写 ...
    
  • 基于对象的跨表查询(子查询)

    #子查询:一条sql语句查询结果给另一条sql语句当做查询的表用
        正向查询按外键字段 ...
        反向查询按表名小写 ...
        	后面有个-set 看情况添加 多的情况加
    基于对象的正向查询
        # 1.查询主键为2的书籍对应的出版社
        # 分两步看 先查询书籍对象
        # book_obj=models.Book.objects.filter(pk=2).first()
        #书籍对象查出版社对象  (当前在book表 外键字段在这 正向 .外键字段)
        # res=book_obj.publish
        # print(res,res.pk,res.name,res.addr)
    
        # 2.查询主键为3的书籍对应的作者
        # 分两步看 先查询书籍对象
        # book_obj=models.Book.objects.filter(pk=3).first()
        #书籍对象查作者对象  (当前在book表 外键字段在这 正向 .外键字段)
        # res=book_obj.authors  #app01.Author.None 出现这个就加一个.all()
        # res=book_obj.authors.all()  #<QuerySet [<Author: 这是对象:迪迦>, <Author: 这是对象:泰罗>]>
        # # print(res)#由于是queryset 列表套数据对象可以for循环拿数据对象然后.字段名 因为是多对多 获取了多个对象
        # for i in res:
        #     print(i.pk)
        #     print(i.name)
        #     print(i.age)
    
        # 3.查询迪迦的详情数据
        # 分两步看 先查询作者对象
        # author_obj=models.Author.objects.filter(name='迪迦').first()
        # 作者对象查询详情对象 (当前在作者表 外键字段在这 正向 .外键字段)
        # res=author_obj.author_detail
        # print(res,res.phone,res.addr)
        """
           小总结
               基于对象的正向查询 数据对象点了外键字段之后
               是否需要再点all 取决于关联的数据项有几个 单个无需点 多个则需要点
        """
        # 4.查询北方出版社出版的书籍
        #先查询出版社对象
        # publish_obj=models.Publish.objects.filter(name='北方出版社').first()
        #出版社对象查询书籍对象  (外键字段在书籍对象里 反向 .表面小写)
        # res=publish_obj.book #'Publish' object has no attribute 'book' 没有book这个字段
        # res=publish_obj.book_set #需要加一个_set 发现app01.Book.None
        # res=publish_obj.book_set.all() #因为是多个对象
        # print(res)    返回的是列表套数据对象
        # for i in res :
        #     print(i.title)
    
        # 5.查询泰罗写过的书籍
        # 先查询作者对象
        # author_obj=models.Author.objects.filter(name='泰罗').first()
        #作者对象查询书籍对象  (当前在author对象里,外键字段在书籍对象里 ,所以反向 .表名小写)
        # res=author_obj.book_set.all()  #加了_set 和all
        # # print(res)
        # for i in res:
        #     print(i.title)
    
        # 6.查询电话是110的作者姓名
        # 先查询作者详情对象
        # authordetail_obj=models.AuthorDetail.objects.filter(phone=110).first()
        # # 作者详情对象查询作者对象 (外键字段在作者 反向查询 .表名小写)
        # res=authordetail_obj.author    #因为是一对一 就一个数据不需要_set 也不需要all
        # print(res.name)
        # print(res.age)
    
        """
        基于对象的反向查询
            如果查询出来的数据对象可以有多个 那么需要 
                表名小写_set.all()
            如果查询出来的数据对象只有一个
                表名小写
        """
    
  • 基于双下划线的跨表查询(对应的sql连表操作)

    #只能用一条orm语句 上面的是两句
    
        # 1.查询主键为2的书籍对应的出版社
        #也符合 正向反向查询    目前在book表 外键字段在这 正向 .外键字段
        # values('publish'): 目前已经到了出版社这个表 拿什么字段直接__字段名
        #返回的是一个列表套字典
        # res=models.Book.objects.filter(pk=2).values('publish__name','publish__addr')
        # print(res)
    
        # 2.查询主键为3的书籍对应的作者
        #先查pk=3的书籍对象 发现在book表查作者表 外键字段在自己这  正向查询 .外键字段名
        # res=models.Book.objects.filter(pk=3).values('authors__name','authors__age')
        # print(res)
        # 3.查询迪迦的详情数据
        #先查询用户对象 用户对象在查询用户数据对象 外键字段在自己这 正向查询
        # res=models.Author.objects.filter(name='迪迦').values('author_detail__addr','author_detail__phone')
        # print(res)
    
        # 4.查询书籍pk为2的作者的电话 需要三个表
        #先查询书籍对象  书籍对象查找作者对象 外键字段在自己这先到作者表__authors 在__author_detail 正向查询
        # res= models.Book.objects.filter(pk=2).values('authors__author_detail__phone')
        # print(res)
    
        """
            总结
            也看正向反向查询 正向 外键字段名__查询的字段名
            values ('外键字段 就已经进入了这个表里 要什么直接__字段名就直接拿就好了') 
            可以到了第二张表继续__外键字段再到第三张表
        """
        # 5.查询北方出版社出版的书籍
        #查出版社对象 出版社对象查询书籍对象  外键不在自己这 反向查询
        # res=models.Publish.objects.filter(name='北方出版社').values('book__title')
        # print(res)
    
    
        # 6.查询泰罗写过的书籍
        #先查询用户对象 用户对象查询书籍对象  外键字段不在自己这 反向查询
        # res=models.Author.objects.filter(name='泰罗').values('book__title')
        # print(res)
    
    
        # 7.查询电话是110的作者姓名
        #先查询用户详情对象 用户详情对象查找用户对象 外键字段不在自己这 反向查询
        # res=models.AuthorDetail.objects.filter(phone=110).values('author__name')
        # print(res)
    
    '''
        总结
        反向查询 小写表名__查询的字段名
        
    '''
    
  • 双下划线进阶操作

    	# 1.查询主键为2的书籍对应的出版社(不能点书籍)
        # 获取出版社对象数据的.filter方法里面先判断
        # 我在出版社这,查找书籍对象 外键字段在书籍对象  反向查询 .表名小写__查询的条件
        # res = models.Publish.objects.filter(book__pk=2)
        # print(res) #获取的是列表套数据对象<QuerySet [<Publish: 这是对象:东方出版社>]>
        #
        # res = models.Publish.objects.filter(book__pk=2).first()
        # print(res.name)  #东方出版社
    
    
        # 2.查询主键为3的书籍对应的作者
        # 作者表对象 查询书籍对象 外键字段在书籍表
        #反向查询 .表名小写__查询的条件
        # res=models.Author.objects.filter(book__pk=3)
        # print(res) #<QuerySet [<Author: 这是对象:迪迦>, <Author: 这是对象:泰罗>]>
        #
        # res = models.Author.objects.filter(book__pk=3) #返回的是列表套数据对象
        # for i in res :
        #     print(i.name) #迪迦  泰罗
    
    
        # 3.查询迪迦的详情数据
        #先查询作者详情数据表  在用作者详情表查询作者表 外键字段不在自己这 反向查询 .表名__查询的字段
        # res= models.AuthorDetail.objects.filter(author__name='迪迦')
        # print(res) #<QuerySet [<AuthorDetail: 这是对象:m78星云>]>
        #
        # res= models.AuthorDetail.objects.filter(author__name='迪迦').first()
        # print(res.phone,res.addr) #110 m78星云
    
        # 4.查询书籍pk为2的作者的电话 用到了三张表
        #先查询 作者详情表 作者详情表查询作者表 再书籍表 反向查询
        #先点到作者表在点到书籍表在加上条件
        # res=models.AuthorDetail.objects.filter(author__book__pk=2)
        # print(res)  #<QuerySet [<AuthorDetail: 这是对象:m78星云>, <AuthorDetail: 这是对象:m98星云>]>
        #
        # for i in res:
        #     print(i.phone) #110 120
        # 5.查询北方出版社出版的书籍
        # 创建书籍表对象  书籍表查询出版社对象 外键字段在自己这  正向查询.外建名字
        # res=models.Book.objects.filter(publish__name='北方出版社')
        # #返回的是列表套数据对象
        # print(res) #<QuerySet [<Book: 这是对象:活着>, <Book: 这是对象:我在精神病院学斩神>]>
        #
        # for i in res: #先循环出来数据对象 在点字段名
        #     print(i.title) #活着   我在精神病院学斩神
    
        # 6.查询泰罗写过的书籍
        # 书籍表 查询作者表 外键字段在自己这 正向查询 .外键字段名
        # res= models.Book.objects.filter(authors__name='泰罗')
        # # 结果是一个列表套数据对象
        # print(res)  #<QuerySet [<Book: 这是对象:人性的弱点>, <Book: 这是对象:三国演义>]>
        #
        # for i in res: #把数据对象循环出来 然后点字段名
        #     print(i.title) #人性的弱点  三国演义
    
    
    
        # 7.查询电话是110的作者姓名
        # 作者表 查询作者详情表 外键字段在自己这 正向查询.外键字段
        # res=models.Author.objects.filter(author_detail__phone=110)
        # print(res) #<QuerySet [<Author: 这是对象:迪迦>]>
    
        # res=models.Author.objects.filter(author_detail__phone=110).first()
        # print(res.name)  #迪迦
    
  • 聚合查询与分组查询

     """聚合查询:aggregate"""
    聚合函数  aggregate
    	max min sum count avg
    需要先导入 from django.db.models import Max,Min,Sum,Count,Avg   
        # 1.统计所有书籍的总价格
        #主要用aggregate里面写聚合函数
        # res=models.Book.objects.aggregate(Sum('price'))
        # print(res) #返回字典
    
        # 2.统计所有书籍的总数
        # res=models.Book.objects.aggregate(Count('pk'))
        # print(res) # 返回字典
    
        # 3.统计价格最高的
        # res=models.Book.objects.aggregate(Max('price'))
        # print(res)
    #还可以写多个 
        #res = models.Book.objects.aggregate(Max('price'),Min('price'),Sum('price'),Count('price'),Avg('price'))
       # print(res)
     """分组查询:annotate"""
        # 1.统计每一本书的作者个数
        #每一本书籍分组   书籍表查 作者表 外键字段在自己这 正向查询
        #使用annotate(别名=条件)  别名必须要起的 因为后面的values中需要使用
        # res = models.Book.objects.annotate(author_num=Count('authors__pk')).values('author_num','title')
        # print(res) #返回的是列表套字典
    
        # 2.统计出每个出版社卖的最便宜的书的价格
        #每个 以出版社对象分组 出版社对象查 书对象 外键字段不在自己这 反向查询 表名小写
        # res= models.Publish.objects.annotate(min_price=Min('book__price')).values('min_price','book__title')
        # print(res)
    
        # 3.统计不止一个作者的图书
        #题目理解 每本图书的作者个数大于一 每本  以图书分组
        # 图书分组 查作者 正向查询  先把每本图书个数拿出来 ,然后再筛选大于1的
        # res = models.Book.objects.annotate(author_num=Count('authors__pk')).filter(author_num__gt=1)
        # for i in res:
        #     print(i.title)
    
    
        # 4.查询各个作者出的书的总价格
        #每个 以作者分组
        #作者对象 查找书籍对象 反向查询 
        # res= models.Author.objects.annotate(sum_price=Sum('book__price')).values('sum_price','name')
        # print(res)
        """
        1.大的分组
            models.表名.objects.annotate  按照models后面的表名分组(主键)
        2.小的分组
            models.表名.objects.values('price').annotate()  按照values括号内指定的字段分组
        """
    
  • F查询与Q查询

#先导入 F查询主要操作数据类型
from django.db.models import F
    # F的功能是获取数据库中字段原有的数据  比如在原有的数据进行增删改查
        from django.db.models import F
    # 1.将所有书籍的价格提升100块
    #使用F
    # models.Book.objects.update(price=F('price')+100)

    # 2.将所有书籍名称后面加上爆款后缀
    # 一般F用来操作数据对象  这个不常用
    # from django.db.models.functions import Concat
    # from django.db.models import Value
    # models.Book.objects.update(title=Concat(F('title'), Value('爆款')))

    # 3.查询库存数大于卖出数的书籍
    # res=models.Book.objects.filter(kucun__gt=F('maichu'))
    # print(res)
    # for i in res:
    #     print(i.title)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值