• django学习-15.ORM查询方法汇总


    1.前言

    django的ORM框架提供的查询数据库表数据的方法很多,不同的方法返回的结果也不太一样,不同方法都有各自对应的使用场景。

    主要常用的查询方法个数是13个,按照特点分为这4类:

    • 方法返回值是可迭代对象QuerySet:all(),filter(),exclude(),order_by(),reverse(),values(),values_list(),distinct();
    • 方法返回值是单个对象:get(),first(),last();
    • 方法返回值是布尔值:exists();
    • 方法返回值是数字:count();

    细节:

    ①.学习任何一个web开发框架比如django,框架都会提供满足90%的开发人员使用的封装的很健壮的很多方法,每个方法都能实现相应的功能,这样开发人员不用花大量时间去写这些类似的方法也就避免了重复造轮子而且开发人员自己造的轮子一般健壮性不高适用场景不多。所以对于使用框架的我们而言,知道框架提供了哪些方法并知道每个方法具体怎么用的例子,我们就能很轻松地进行业务开发!

    2.数据准备

    为了结合实际例子,来验证这13个查询方法怎么使用,需要提前在指定的数据表里造好数据。

    所以,我选择用【hello_person】表的这三条数据当做测试数据。

    3.方法返回值是可迭代对象QuerySet的每个查询方法的如何使用的完整记录

    细节:

    ①.通过之前的接口调试,我们知道视图函数【search_person】已经能被正常调用并返回我们预期的结果值。所以我们每次验证一个查询方法,就可以通过改造这个视图函数【search_person】里的相关代码逻辑来进行验证。

    3.1.查询方法【all()】如何使用的完整记录

    细节:

    ①.首先,我们知道查询一张数据表【hello_person】的所有数据的原生sql语句是:select * from hello_peroson。

    ②.但是,我们通过ORM框架提供的任何一个方法就都不需要写原生sql语句,比如执行这行代码【allData = 一张数据表对应的类名称.objects.all()】就能返回这张表的所有数据即所有数据都存储在这个变量【allData】里,变量【allData】是可迭代对象QuerySet,即我们要记住变量【allData】在此时是一个可迭代对象,并没有直接给我们返回全部数据而是间接返回全部数据。如果要取出可迭代对象【allData】里的具体的数据表数据,必须要用for循环进行读取,因为for循环就是专门用来处理列表和字典和元祖和可迭代对象的这些可被迭代的数据类型!

    ③.可迭代对象QuerySet的初步理解:可以把python语言里的可迭代对象QuerySet看成是java语言里的结果集,结果集可以看成是列表,结果集的作用是用于存储每个不同的对象/不同的元祖/不同的字典。而我们也知道每个对象都是唯一的因为每个对象内存地址都是唯一的,每个类被实例化一次后就会生成对应的一个对象,我们可以通过对象去调用类里面的相关类属性相关方法去获取我们想要的具体的数据表表数据。

    ④.通过ORM框架提供的【all() 】方法的返回值是一个可迭代对象QuerySet类型数据,该类型数据类似于list。这个可迭代对象QuerySet类型数据里面每个数据都是模型类的对象。

    ⑤.

    问题:

    结果集为什么基本用来存储从数据表获取的数据?

    大概答案:

    假如一张数据表有10万条数据,结果集里肯定有10万个不同的对象,通过每个对象可以方便后期获取对应的这条数据表数据的相关表字段数据。

    django会对【all()】方法返回的这个可迭代对象QuerySet类型数据进行缓存,这是为了提高查询效率。也就是说,在我们创建一个迭代对象QuerySet的时候,django并不会立即向数据库发出查询命令而只是获取到对应数据里每条表数据对应的每个不同的模型类对象,只有在我们需要用到这个迭代对象QuerySet(通过for循环去调用模型类的对象)的时候才会触发调用模型类对象里的相关方法或者相关类属性去执行相关sql语句的查询命令。

    ⑥.

    问题:如何用比较接地气的文案来描述用于存储对象的结果集的作用?

    大概答案:

    比如一张数据表A里有10条数据,把一张数据表A的每条数据看成一个结果,我们就需要用每个不同的对象去装载每个不同的结果。

    就比如:一辆车装一个人,一个对象装一个结果。

    然后现在有10个不同的人,就必须需要10辆不同的车。

    可以把结果集理解为是一个很大的装车的集装箱,可以通过这个集装箱装这10辆车。

    最终,我们拿到了这个集装箱,可以通过【for循环】这个开集装箱工具去获取到所有的车所有的人和每个人不同的具体数据。

    ⑦.

    问题:

    比如我一张数据表A里有1万条表数据,现在我想要获取到这张数据表A所有表字段的具体值,有以下这两个方案:
    方案1:自己直接写一条原生aql语句,直接返回这1万条数据的所有表字段值的具体值。    
    方案2:通过orm框架提供的一个方法all()返回有包含1万条数据对应的对象的结果集,接着通过对象去调取相关类属性或者方法去获取到表字段值的具体值。
    请问,我该采用哪个方案?

    大概答案:
    无论是基于java语言还是python语言开发的现有框架的设计都是基于ORM设计的,就是说数据自动映射对象,在业务开发过程中,任何操作也都是基于对象操作,这才符合ORM原则。
    像java相关的:Mybatis, JPA, springJDBC,像python相关的:django,这些框架涉及的数据库操作都是基于ORM。
    如果我们想直接获取表数据,一般原生的JDBC即sql语句是可以实现的,但这不是基于对象操作,不符合ORM原则。
    所以说,方案1和方案2其实都可以采用,但从对象操作的角度来看,主流都是采用方案1。
     
     

    3.1.1.第一步:我们可以打印出可迭代对象的值是什么。

     

     

    3.1.2.第二步:查询方法【all()】的具体使用。

     

    细节:

    ①.相关源码如下:

    def search_person(request):
        '''1.通过方法all()间接获取到hello_person表里的三个表字段id,name,age的所有数据'''
        # 第一步:新增三个数据类型为str的变量,初始值都设置为空,用于后续存储数据;
        ids   = ''
        names = ''
        ages  = ''
        # 第二步:通过调用方法all(),返回一个数据类型为可迭代对象QuerySet的变量res;
        res = Person.objects.all()
        # 第三步:通过for循环,获取我们想要的数据;
        for i in res:
            ids = ids + " " + str(i.id)      # 我们把表字段id的值都存储在变量ids;
            names = names + " " + i.name     # 我们把表字段name的值都存储在变量names;
            ages  = ages + " " + str(i.age)  # 我们把表字段age的值都存储在变量ages;
    
        # 第四步:把数据返回给前端页面;
        return HttpResponse('''
                            表字段id所有的值汇总:%s;<br/>
                            表字段name所有的值汇总:%s;<br/>
                            表字段ages所有的值汇总:%s;<br/>
                             '''%(ids,names,ages))

    3.2.查询方法【filter()】如何使用的完整记录

    细节:

    ①.首先,我们知道查询一张数据表【hello_person】里的符合条件的数据的原生sql语句一般比如是:select * from hello_peroson where id = 9。

    ②.我们通过ORM框架提供的【filter()】方法也可以快速实现①的功能。

    ③.【filter() 】方法的返回值是一个可迭代对象QuerySet类型数据,该类型数据类似于list。这个可迭代对象QuerySet类型数据里面每个数据都是模型类的对象。

    3.2.1.第一步:查询方法【fliter()】的具体使用。

      

    细节:

    ①.方法fiter()的传参规则。

    3.3.查询方法【exclude()】如何使用的完整记录

    细节:

    ①.【exclude() 】方法的返回值也是一个可迭代对象QuerySet,返回值都是不符合查询条件的数据。

    ②.【exclude() 】方法在实际开发中基本少用,基本都采用【filter()】方法。

    ②.【exclude() 】方法的返回值是一个可迭代对象QuerySet类型数据,该类型数据类似于list。这个可迭代对象QuerySet类型数据里面每个数据都是模型类的对象

    3.3.1.第一步:查询方法【exclude()】的具体使用。

     

     

    3.4.查询方法【order_by()】如何使用的完整记录

    细节:

    ①.【order_by() 】方法的返回值也是一个可迭代对象QuerySet,返回值都是符合排序条件的数据。

    ②.【order_by() 】方法的返回值是一个可迭代对象QuerySet类型数据,该类型数据类似于list。这个可迭代对象QuerySet类型数据里面每个数据都是模型类的对象。

    ③.入参的相关注意点:

    • 参数的字段名要加引号。
    • 如果要实现降序功能,要在字段名前面加个负号【-】。

    3.4.1.第一步:查询方法【order_by()】的具体使用。

    3.5.查询方法【reverse()】如何使用的完整记录

    细节:

    ①.【reverse() 】方法的返回值也是一个可迭代对象QuerySet,【reverse() 】方法用于对查询结果进行反转。

    ②.【reverse() 】方法在实际开发中基本少用,基本都采用【order_by()】方法。

    ③.【reverse() 】方法的返回值是一个可迭代对象QuerySet类型数据,该类型数据类似于list。这个可迭代对象QuerySet类型数据里面每个数据都是模型类的对象。

    3.5.1.第一步:查询方法【reverse()】的具体使用。

    3.6.查询方法【values()】如何使用的完整记录

    细节:

    ①.【values() 】方法的返回值也是一个可迭代对象QuerySet,【values() 】方法用于查询部分字段或者全部字段的数据。

    ②.如果要查询全部字段的数据,【values() 】方法的入参字段数要为0;

    ③.【values() 】方法的返回值是一个可迭代对象QuerySet类型数据,该类型数据类似于list这个可迭代对象QuerySet类型数据里面每个数据都不是模型类的对象而是可迭代的字典噢,字典里的键是表字段,值是表字段对应的数据。

    3.6.1.第一步:查询方法【values()】的具体使用。

     

    3.7.查询方法【values_list()】如何使用的完整记录

    细节:

    ①.【values_list() 】方法的返回值也是一个可迭代对象QuerySet,但【values_list() 】方法用于查询部分字段或者全部字段的数据。

    ②.如果要查询全部字段的数据,【values_list() 】方法的入参字段数要为0;

    ③.【values_list() 】方法的返回值是一个可迭代对象QuerySet类型数据,该类型数据类似于list这个可迭代对象QuerySet类型数据里面每个数据都不是模型类的对象而是元祖哦,元组里放的是查询表字段对应的数据。

    3.7.1.第一步:查询方法【values_list()】的具体使用。

    3.8.查询方法【distinct()】如何使用的完整记录

    细节:

    ①.【distinct()】方法的返回值也是一个可迭代对象QuerySet。

    ②.【distinct()】方法的返回值是一个可迭代对象QuerySet类型数据,该类型数据类似于list。这个可迭代对象QuerySet类型数据里面每个数据都不是模型类的对象,而是每个元祖,元组里放的是查询字段对应的数据。

    ③.【distinct()】方法对模型类的对象去重没有意义,因为每个对象都是一个不一样的存在。所以【distinct()】方法一般是跟 【values】方法 或者 【values_list】方法 一起使用,但如果跟【all()】方法一起使用是产生不了去重的效果。

    ④.【distinct()】方法的作用:用于对数据进行去重。

    3.8.1.第一步:查询方法【distinct()】的具体使用。

    4.方法返回值是单个对象的每个查询方法的如何使用的完整记录

    4.1.查询方法【get()】如何使用的完整记录

    细节:

    ①.【get()】方法的返回值是一个模型类的对象

    ②.【get()】方法用于查询符合条件的返回模型类的对象且符合条件的对象只能为一个,如果符合筛选条件的对象超过了一个或者没有一个都会抛出错误。

    4.1.1.第一步:查询方法【get()】的具体使用。

    4.2.查询方法【first()】如何使用的完整记录

    细节:

    ①.【first()】方法返回符合查询条件的结果里的第一条数据且返回的数据是模型类的对象。

    4.2.1.第一步:查询方法【first()】的具体使用。

    4.3.查询方法【last()】如何使用的完整记录

    细节:

    ①.【last()】方法返回符合查询条件的结果里的最后一条数据且返回的数据是模型类的对象。

    4.3.1.第一步:查询方法【last()】的具体使用。

    5.方法返回值是布尔值的每个查询方法的如何使用的完整记录

    5.1.查询方法【exists()】如何使用的完整记录

    细节:

    ①.【exists()】方法用于判断查询的结果 QuerySet 列表里是否有数据。

    ②.【exists()】方法返回值的数据类型是布尔值,有数据则返回值为true,没有数据则返回值为false。

    5.1.1.第一步:查询方法【get()】的具体使用。

    6.方法返回值是数字的每个查询方法的如何使用的完整记录

    6.1.查询方法【count()】如何使用的完整记录

    细节:

    ①.【count()】方法用于查询数据的数量且返回的数据是整数。 

    6.1.1.第一步:查询方法【count()】的具体使用。

    7.相关的学习资料地址

    ①.django的ORM框架提供的查询数据库表数据的所有方法具体使用,可以查看该菜鸟教程地址:https://www.runoob.com/django/django-orm-1.html

  • 相关阅读:
    [Docker] Windows 宿主环境下,共享或上传文件到容器的方法
    [Docker]
    [Docker]
    [Docker]
    [Windows]
    [Linux] 树莓派 4B 安装 Ubuntu 19.10 (Eoan Ermine) IOT 版
    [Linux]
    [.Net] 什么是线程安全的并发集合
    [IOT]
    c++库大全
  • 原文地址:https://www.cnblogs.com/xiamen-momo/p/14330712.html
Copyright © 2020-2023  润新知