Django学习小记(六)-----数据库ORM(函数)

一、例表结构

在这里插入图片描述

  • 正向跨表:指显式或隐式通过外键,从外键所在的表到外键指向的表
  • 反向跨表:指显式或隐式通过外键,从外键指向的表到外键所在的表

二、返回数据类型

2.1 单object对象

代表函数:first,last
功能:返回一个object对象,即代表一行,点运算符可获得具体数据

  • 写法

    名称写法返回
    本表操作res = models.Stu.objects.first()res为Stu object (1),表Stu的第一行
    正向跨表res = models.Stu.objects.first().stu_detailres为StuDetail object (2),表StuDetail的第二行
    反向跨表res = models.Publish.objects.first().book_setres为api.Book.None,效果等同于model.Book.objects

2.2 obj列表式QuerySet对象

代表函数:filter,all(性能较低,避免)
功能:返回一个queryset对象,即代表多行的一个列表,点运算符可获得一个object对象

  • 写法

    名称写法返回
    本表操作res = models.Publish.objects.all()<QuerySet[
    <Publish: Publish object (1)>,
    <Publish: Publish object (2)>
    ]>
    正向跨表res = models.Stu.objects.filter(stu_detail__height=165.4)<QuerySet [
    <Stu: Stu object (2)>
    ]>
    反向跨表res = models.StuDetail.objects.filter(stu__id=3)<QuerySet [
    <StuDetail: StuDetail object (3)>
    ]>
  • QuerySet–>object–>具体数据

    def dblink(request):
        # 拿到Stu的所有行的QuerySet对象
        stu = models.Stu.objects.all()
        for item in stu:
            # 正向查询操作:本表项;本表外键项的值;连表:执行跨表取值,stu_detail为Stu的外键
            print(item.name, item.stu_detail_id, item.stu_detail.height)
    
        # 反向查询操作
        
        # 首先取Publish表中第二项的object对象
        obj = models.Publish.objects.last()
        print('出版社:', obj.name)
        
        # 然后obj.外键所在表小写_set.all(),返回Book表的QuerySet对象
        res = obj.book_set.all()
        for row in res:
        	print('包含科目:', row.name)
    
        return HttpResponse('操作dblink结束')
    
  • 显示
    在这里插入图片描述

2.3 字典列表式QuerySet对象

代表函数:values
功能:返回一个字典列表的QuerySet对象

  • 写法

    名称写法返回
    本表操作res = models.Stu.objects.values('id', 'name')<QuerySet [
    {‘id’: 1, ‘name’: ‘sam’},
    {‘id’: 2, ‘name’: ‘duke’},
    {‘id’: 3, ‘name’: ‘jane’}
    ]>
    正向跨表res = models.Stu.objects.values('id', 'stu_detail__gender')<QuerySet [
    {‘id’: 2, ‘stu_detail__gender’: 1},
    {‘id’: 1, ‘stu_detail__gender’: 2},
    {‘id’: 3, ‘stu_detail__gender’:0}
    ]>
    反向跨表res = models.StuDetail.objects.values('id', 'stu__name')<QuerySet [
    {‘id’: 1, ‘stu__name’: ‘duke’},
    {‘id’: 2, ‘stu__name’: ‘sam’},
    {‘id’: 3, ‘stu__name’: ‘jane’}
    ]>
  • 数据取法

    def dblink(request):
        res = models.StuDetail.objects.values('id', 'stu__name')	# 仅写stu等同于stu__id
        print(res)
        for item in res:
            print(item['id'], item['stu__name'])
        return HttpResponse('操作结束')
    
  • 显示

    <QuerySet [{'id': 1, 'stu__name': 'duke'}, {'id': 2, 'stu__name': 'sam'}, 
    {'id': 3, 'stu__name': 'jane'}]>
    1 duke
    2 sam
    3 jane
    

2.4 元组列表式QuerySet对象

代表函数:values_list
功能:返回一个元组列表式QuerySet对象

  • 写法

    名称写法返回
    本表操作res = models.Stu.objects.values_list('id', 'name')<QuerySet [(1, ‘sam’), (2, ‘duke’), (3, ‘jane’)]>
    正向跨表res = models.Stu.objects.values_list('id', 'stu_detail__gender')<QuerySet [(2, 1), (1, 2), (3, 0)]>
    反向跨表res = models.StuDetail.objects.values_list('id', 'stu__name')<QuerySet [(1, ‘duke’), (2, ‘sam’), (3, ‘jane’)]>
  • 数据取法

    def dblink(request):
    	res = models.StuDetail.objects.values_list('id', 'stu__name')
    	print(res)
    	for item in res:
    		print(item[0],item[1])
    	return HttpResponse('操作结束')
    
  • 显示

    <QuerySet [(1, 'duke'), (2, 'sam'), (3, 'jane')]>
    1 duke
    2 sam
    3 jane
    

三、常规函数

3.1 create函数

3.1.1 create函数

  1. 常规写法:models.Stu.objects.create(name='sam', stu_detail_id=2)
  2. 进阶写法:
    • 写法:obj = models.Stu.objects.create(name='sam', stu_detail_id=2)
    • 意义:obj代表这一行,创建后取得这行的object对象
  3. 字典写法:
    def dblink(request):
    	# name_list可以写成[{},{},]形式,配合for循环
    	   name_list = {'id': '3', 'name': 'publish_test'}
    	   res = models.Publish.objects.create(**name_list)
    	   print(res)
    	   return HttpResponse('<h1>处理结束</h1>')
    

3.1.2 bulk_create函数

  • 功能:批量生成,并控制每次任务量
  • 写法
    def dblink(request):
    	   obj_list = {
    	       models.Publish(id=3, name='publish_1'),		# 此语句在内存中生成一个publish的object对象
    	       models.Publish(id=4, name='publish_2'),
    	       models.Publish(id=5, name='publish_3'),
    	   }
    	   # 										 字典,数据库中每次创建记录的最大个数
    	   res = models.Publish.objects.bulk_create(obj_list, 2)
    	   print(res)
    	   # [<Publish: Publish object (3)>, <Publish: Publish object (4)>, <Publish: Publish object (5)>]
    	   return HttpResponse('<h1>处理结束</h1>')
    

3.1.3 get_or_create函数

  • 功能:检测符合条件行是否存在,存在返回,不存在则新建
  • 写法
    def dblink(request):	
    	# obj:存在接收返回的object,不存在接收新增的object
    	# exit_y:判断是否为新建的object,布尔值
        obj, exit_y = models.StuDetail.objects.get_or_create(
            height=166.4,								# 筛选条件一
            gender=2,									# 筛选条件二
            defaults={'birthday': '1987-6-6'}			# 若不存在,需在此填写值notnull的各列
        )
        print(obj, exit_y)
        return HttpResponse('<h1>处理结束</h1>')
    

注意:若检测有多个符合条件,则报错
措施:去重distinct,或者加try语句

3.1.4 update_or_create函数

  • 功能:检测符合条件行是否存在,存在更新,不存在则新建
  • 写法:同3.1.3

3.2 all函数

  • 常规用法
    def dblink(request):
        res = models.Stu.objects.all()					# 性能优化只针对这一行
        for item in res:
            print(item.name, item.stu_detail.height)	# 连表导致性能下降
        return HttpResponse('<h1>处理结束</h1>')
    
  • 性能优化(针对外键连表):
    • select_related
      • 触发情境:数据量小,参数为外键
      • 写法:res = models.Stu.objects.all().select_related('stu_detail')
    • prefetch_related
      • 触发情境:数据量庞大,参数为外键
      • 写法:res = models.Stu.objects.all().prefetch_related('stu_detail')

四、filter函数

  • 筛选
    • 包含:    models.Stu.objects.filter(见3.1)
    • 不包含:models.Stu.objects.exclude(同filter)

4.1 条件筛选

  • 数字比较

    写法意义写法意义
    __gt大于__gte大于等于
    __lt小于__lte小于等于
    __range在什么区间内__in存在于一个list范围内

    写法:

    • 数字:models.Stu.objects.filter(id__lte=2),id≤2的queryset
    • 区间:models.Stu.objects.filter(id__range=[2,3]),id只能取2~3,包含2,3的queryset
    • 范围:models.Stu.objects.filter(id__in=[1,3]),id只能取1、3的queryset
  • 字符筛选

    写法意义写法意义
    __startswith以什么字符开始__istartswith以什么字符开始,忽略大小写
    __endswith以什么字符开始__iendswith以什么字符开始,忽略大小写
    __contains包含字符__icontains包含字符,忽略大小写

    写法:models.Book.objects.filter(name__startswith='mat').first(),选择以‘mat’开头的object

  • 日期筛选

    写法意义写法意义
    __year日期字段的年__month日期字段的月
    __day日期字段的日__isnull=True/False判断是否为空

    补充:
    写法:models.StuDetail.objects.filter(birthday__day=9).first(),选择日期的日是9的object
    比较写法:res = models.StuDetail.objects.filter(birthday__day__gt=9).first()

4.2 复合写法

  • 字典条件:将条件以字典方式写入
  • 写法
    def dblink(request):
    	# 以下为条件字典写法,默认以and逻辑筛选
        con = {
            'id__gt': 1,
            'height': 180.3,
        }
        res = models.StuDetail.objects.filter(**con)
        print(res)
        return HttpResponse('<h1>处理结束</h1>')
    

4.3 Q函数

  • 功能:构造复杂的筛选条件
  • 简单写法
    from django.db.models import Q
    
    def dblink(request):
    	# Q 对象可以使用 & | ~ (与 或 非)操作符进行组合
        res = models.StuDetail.objects.filter(Q(id__gt=1) & ~Q(height=180.3))
        print(res)				
        # 返回:<QuerySet [<StuDetail: StuDetail object (2)>]>
        return HttpResponse('<h1>处理结束</h1>')
    
  • 前后端交互
    from django.shortcuts import HttpResponse
    from api import models
    from django.db.models import Q
    
    def dblink(request):
        # 前端构造此字典
        con_dict = {
       		 # k1、k2、k3之间为or连接,列表中每个数字为and连接
            'k1': [1, 2, 3, 4],
            'k2': [1, 2],
            'k3': [13, 22],
        }
    
        # 构造筛选条件,con( q and q and q ),q内部为or
        con = Q()
        # 此处v循环取每一行的列表项
        for v in con_dict.values():
        	# 创建q实例
            q = Q()
            # k1、k2、k3之间为or连接
            q.connector = 'OR'
            # 取出列表中的每个数字
            for i in v:
                # 列表中每个数字为and连接,’id‘也可以为’id__gt‘
                q.children.append(('id', i))
            # 将q以and逻辑加入到con里
            con.add(q, 'AND')
            
        # 后端接收字典并进行筛选
        res = models.StuDetail.objects.filter(con)
        print(res)
        return HttpResponse('<h1>处理结束</h1>')
    

4.4 F函数

  • 功能:在原数据基础上做操作,也可用在filter
  • 写法
    from django.db.models import F
    
    def dblink(request):
    	# 将本表所有行中height列数据都自加100,也可以先filter再update
        res = models.StuDetail.objects.update(height=F('height')+100)
        print(res)
        # 输出3,为影响到的行数
        return HttpResponse('<h1>处理结束</h1>')
    

五、统计类函数

5.1 聚合查询(aggregate)

  • 功能:针对整个表进行统计操作
  • 写法
    # 导入函数              求总行数,合计,最大值,最小值,平均值
    from django.db.models import Count, Sum, Max, Min, Avg
    
    def dblink(request):
    	# Count:计算行数,参数若为'id'、'name'、'stu_detail_id'结果相同
        res = models.Stu.objects.aggregate(sum_line=Count('name'))
        print(res)
        # 返回:{'sum_line': 3},纯字典
        return HttpResponse('<h1>处理结束</h1>')
    

5.2 分组查询(annotate)

  • 功能:将某一列相同值进行聚合,即分组,进而使用聚合函数求值
  • 写法
    # 导入函数              求总行数,合计,最大值,最小值,平均值
    from django.db.models import Count, Sum, Max, Min, Avg
    
    def dblink(request):
    	# 		  待统计的表	 或values_list  分组依据的列		 	统计值存放列的别名
        res = models.Book.objects.values('publish_id').annotate(sum_line=Count('id'))
        print(res)
        # 返回:<QuerySet [{'publish_id': 1, 'sum_line': 1}, {'publish_id': 2, 'sum_line': 2}]>
        return HttpResponse('<h1>处理结束</h1>')
    
  • filter函数
    • 后置:聚合函数处理后过滤,可过滤sum_line列,放在annotate函数后
    • 前置:分组前过滤,放在values函数前

六、函数拾遗

6.1 小众函数

  • 去重distinct:res = models.Book.objects.values('publish_id').distinct(),配合values、values_list,返回queryset
  • 排序order_by:res = models.Stu.objects.all().order_by('id')
  • 反序reverse:res = models.Book.objects.all().order_by('id').reverse(),需紧跟order_by
  • 主键筛选in_bulk:res = models.Book.objects.in_bulk([1,3]),等价于models.Book.objects.filter(id__in=[1, 3])
  • 存在与否exists:exist_y = models.Book.objects.filter(id=1).exists(),返回布尔值

6.2 原生sql语句

  • extra函数:略
  • raw函数:略
  • Django翻译后的SQL语句:print('res.query')

跳转至总篇目录

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值