• 周一. 5月 27th, 2024

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

Django ORM框架之CRUD操作

admin

11月 28, 2021

前言:上篇文章中简单记录了Django通过ORM框架中的对象与数据库中的对象映射,即如何创建模型类、定义类属性、生成迁移脚本、执行迁移脚本生成数据表等操作。本篇文章会继续记录Django通过ORM框架操作数据库中的数据,即生成数据表之后对表中数据的操作:CRUD(创建、读取(查询)、更新、删除)。

一、创建数据(C)

1、创建主表数据(无外键字段)

方式一:1)实例化模型类,根据字段定义规则传递关键字参数;

    2)调用模型对象的save()方法

注意:此种方式必须要调用save方法,才会执行sql语句,将数据写入到表中

示例:在调试模式下运行,查看代码执行过程

PS:此处需要添加监听器,监测否有sql语句执行,那么如何添加该监听器呢?

1)导入django.db中的connection

2)调试模式下,在Variables中添加监听器,输入connection.queries

运行代码可见:创建模型对象project_obj后,并未监测到sql语句执行

查看tb_projects数据表中也无数据生成

执行save方法后,监听到sql语句执行,查看数据表中有数据生成

 

方式二:模型类名.objects.create(关键字参数)

注意:1)此种方式无需调用save方法,因为在create方法源码里实现了实例化模型类和调用save方法,并将模型对象返回

     2)模型类名.objects 返回的是Manage对象,是一个管理器对象

示例:

2、创建从表数据(有外键字段,需要解决从表外键对应的主表数据如何传值)

方式一:1)获取主表模型对象

    2)从表模型类名.objects.create(关键字参数, 外键名=主表模型对象)

示例:

方式二:1)获取主表模型对象的id属性值

    2)从表模型类名.objects.create(关键字参数, 外键名_id=主表模型对象的id属性值)

示例:

二、读取数据(R)

1、读取多条数据

1)读取数据表中的所有数据:模型类名.objects.all()

示例:

注意:a)模型类名.objects.all() 返回的是 QuerySet 对象,QuerySet 对象中包裹着多个模型对象

   b)QuerySet 对象类似list,支持正值索引取值、正值切片操作、len()方法求长度、还支持迭代(可以使用for循环对查询集进行迭代),可以使用list(QuerySet对象)将去转换为list

     c)QuerySet 对象具有惰性查询的特性,即在真正’用’数据时,才会执行sql语句

     d)QuerySet 对象具有链式调用特性,即filter方法可以继续调用filter方法(或all方法)

   e)QuerySet 对象常用方法:

    first()  获取查询集中第一条数据(即模型对象)

    last()  获取查询集中最后一天数据(即模型对象)

    count()  获取查询集中有多少条数据(即模型对象的个数)

    exists()  判断查询集是否为空

2)读取符合条件的数据(条件查询):模型类名.objects.filter(查询条件)  或   模型类名.objects.exclude(查询条件)

** 查询条件格式:字段名__查询类型=具体值

** filter方法和exclude方法支持多种查询类型:

 a)等于:    字段名__exact=具体值  或 字段名=具体值

 b)大于:    字段名__gt=具体值

 c)大于等于:  字段名__gte=具体值

 d)小于:    字段名__lt=具体值

 e)小于等于:  字段名__lte=具体值

 f)包含:     字段名__contains=具体值,不忽略大小写;字段名__icontains=具体值,忽略大小写

 g)以…开头:   字段名__startswith=具体值,不忽略大小写;字段名__istartswith=具体值,忽略大小写

 h)以…结尾:   字段名__endswith=具体值,不忽略大小写;字段名__iendswith=具体值,忽略大小写

 i)是否为空:   字段名__isnull

** filter方法与exclude方法的区别:filter方法筛选出符合条件的数据并返回;exclude方法筛选出符合条件的数据后,取补集返回。

示例:

Projects.objects.filter(id__gt=1) –> 查询id>1的数据

Projects.objects.exclude(id__gt=1) –> 查询id不大于1的数据 (即id<=1的数据)

2、读取单条数据

方式一:模型类名.objects.get(查询条件)

示例:

注意:1)如果条件无法查询出结果(即没有符合条件的数据)时,此种方式会抛出异常

   2)如果条件查询出来的结果为多条时,此种方式也会抛出异常

     3)使用此种方式查询时,最好使用具有唯一约束的条件去查询

   4)get方法查询返回的结果是模型对象

   5)一般使用get方法查询时,会使用try…catch捕获异常

方式二:模型类名.objects.filter(查询条件)

示例:

 

注意:1)使用filter方法查询时,如果符合查询条件的数据不存在,则返回空的QuerySet对象

   2)如果符合查询条件的数据为多条,则将这些数据(模型对象)包裹到QuerySet对象中返回

另:在ORM框架中,会自动给每个模型类的逐渐添加一个别名pk,即使用主键查询时,可以使用pk__查询类型=具体值

3、通过从表数据获取主表数据(实际上是通过从表外键字段来获取)

1)获取从表模型对象

2)从表模型对象.外键字段名

示例:在接口表中查询id为1的接口的所属项目信息

注意:虽然从表中外键字段值村粗的是主表模型对象的id,但通过“从表模型对象.外键字段名”获取的是主表模型对象 

4、通过主表数据获取从表数据

1)获取主表模型对象

2)主表模型对象.从表模型类名小写_set.查询方法(get/filter/exclude/all)

示例:查询name为‘测试项目’的项目所包含的所有接口信息

注意:1)从表模型类名小写_set 是ORM框架提供给主表模型对象的默认属性主表模型对象.从表模型类名小写_set 返回的是从表的manage对象

   2)从表模型类名小写_set 可以修改,在定义外键字段时,可以指定related_name属性的值,related_name代表的是主表获取从表数据的引用名称

   3)不属于多表查询(执行了多条查询语句)

5、多表查询(关联查询)

1)通过主表参数来获取从表数据:要获取的是从表的数据,所以在从表查询,查询条件为主表字段的限制条件

  即:从表模型类名.objects.filter(外键名__主表字段名__查询类型=具体值)

示例:查询leader为‘ppd’的项目的所有接口信息

 

注意:1)外键名__ 相当于是获取主表的引用,projects__name相当于是在使用主表的name字段做过滤

   2)多表关联:外键1__外键2__外键3__xx字段__查询类型=具体值

2)通过从表参数来获取主表数据:要获取的是主表数据,所以在主表查询,查询条件为从表字段的限制条件

   即:主表模型类名.objects.filter(从表模型类名小写__从表字段名__查询类型=具体值)

示例:查询接口名称中包含‘登录’的所有项目信息

6、查询条件间的逻辑关系

1)’与’ 关系

方式一:在同一个filter方法内部,添加多个关键字参数(查询条件),这些参数之间为’与’关系

示例:查询name中包含’2’,且leader也包含’2’的项目信息

方式二:多次调用filter方法,多个filter方法的查询条件间为’与’关系

示例:

方式三:通过Q查询实现,即 模型类名.objects.filter(Q(字段名__查询类型=具体值) & Q(字段名__查询类型=具体值))

2)’或’ 关系

通过Q查询实现:1)导入Q类,from django.db.models import Q

         2)实例化Q对象,参数为查询条件,多个Q对象之间使用 | ,那么这些Q对象之间为’或’关系

即:模型类名.objects.filter(Q(字段名__查询类型=具体值) | Q(字段名__查询类型=具体值))

示例:查询name包含’2′ 或 leader是’yxj’的项目信息

7、对查询结果排序

通过QuerySet对象(或manager对象)提供的order_by方法实现排序,默认按照指定的字段升序排序,如果字段名前加“-”,则表示降序排序

即:QuerySet对象(或manager对象).order_by(‘字段名1’, ‘字段名2’, … )

示例:查询name包含’2’的项目信息,并通过name进行降序排序,再通过leader进行升序排序

 

三、更新数据(U)

1、更新一条数据:

方式一:通过给模型对象属性赋新值 实现数据更新

  1)获取要更新数据的模型对象:模型类名.objects.get(查询条件)

  2)给要修改的模型对象属性赋值:模型对象.属性 = 新值

  3)调用模型对象的save方法:模型对象.save()

示例:

更新id为1的项目的name和leader信息

注意:1)从上图可看出,调用save方法执行的sql语句为完整更新,即 虽然我只给name和leader赋新值,但执行save方法后,该条数据的所有字段值都进行了更新

   2)使用此种方式更新数据时,往往需要给save方法传递update_fields参数(序列类型),指定需要更新的字段名称

方式二:调用查询集对象的update方法实现

    即:模型类名.objects.filter(具有唯一约束的字段条件).update(字段名=’新值’)

2、更新多条数据 :通过调用查询集对象的update方法实现数据更新

   即:模型类名.objects.filter(查询条件).update(字段名1=’新值1′, 字段名2=’新值2′, … )

示例:更新name含有’22’的项目的leader为’小潘达’

注意:1)update方法返回的是更新成功的数据条数

   2)通过给模型对象属性赋值的方式更新数据,需要手动的调用save方法后才会执行sql语句,将更新的数据写入数据表,而update方法不需要调用save方法

四、删除数据(D)

1、删除一条数据:通过调用模型对象的delete方法实现数据删除

  1)获取要删除的数据的模型对象:模型类名.objects.get(查询条件)

  2)调用模型对象的delete方法:模型对象.delete()

示例:删除id为6的项目数据

2、删除多条数据:通过调用QuerySet对象的delete方法实现多条数据的删除

  1)获取要删除的数据查询集对象:模型类名.objects.filter(查询条件)

  2)调用查询集对象的delete方法:查询集对象.delete()

示例:删除name包含’yxj’的项目数据

总结:本篇文章记录了Django ORM框架对数据进行增删改查操作,重点和难点都在查询数据上,单表查询、多表查询都需要多多练习才能掌握其中的知识点!

本博客仅为本人学习过程中的记录,欢迎一起交流经验。

《Django ORM框架之CRUD操作》有2个想法

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注