0


【django】模型类中数据的增删改查操作总结

在这里插入图片描述


文章目录

一、数据库数据操作

一旦创建数据模型后,django自动给与一套数据库 抽象API,用来创建、检索、更新和删除对象。
为了方便调试,可以通过下面的命令进入django shell

python manage.py shell

使用这个命令进入的shell环境会包含当前的django项目的依赖,直接通过python命令进入的shell不会包含django依赖。

在日志等级debug=True,下面的代码可以打印除所有执行过的sql

from django.db import connection
print(connection.queries)

二、创建对象

创建一个模型对象,可以直接通过关键字参数实例化,然后调用save方法,将其存入数据库

from crm.models import Student
s=Student(**fields)
s.save()

这在幕后执行的INSERT 语句

注意:django在调用save()方法才会操作数据。save()方法没有返回值

还有一种创建对象并一步到位的create()方法
使用管理器上的create方法,会直接写入数据库
create方法会返回创建的对象

**

Student.objects.create(**fields)

**

三、批量创建对象

方法一:for循环迭代

批量创建对象可以利用上面的方法和for循环结合使用,但是效率比较低,会执行多条sql

data=[{"name":"james","age":18,"phone":"13888888888"},{"name":"kelai","age":22,"phone":"13688888888"},{"name":"kd","age":19,"phone":"13888888777"},]for item in data:
    s=Student(**item)
    s.save()

方法二:bulk_create()

bulk_create()方法可以有效的将提供的对象插入到数据库表(一般来说,不管多少个数据,只需要一条sql),它返回创建的对象列表

data=[{"name":"harden","age":18,"phone":"13888878228"},{"name":"curry","age":22,"phone":"13688883388"},{"name":"ad","age":19,"phone":"13888855577"},]

Student.objects.bulk_create([
    Student(**(data[0])),
    Student(**(data[1])),
    Student(**(data[2]))])

执行的sql语句:

print(connection.queries[-1]){'sql':"INSERT INTO `t_student` (`name`, `age`, `phone`, `address`, `create_time`, `channel_id`) VALUES ('harden', 18, '13888878228', NULL, '2023-01-06 07:21:25.347180', NULL), ('curry', 22, '13688883388', NULL, '2023-01-06 07:21:25.347180', NULL), ('ad', 19, '13888855577', NULL, '2023-01-06 07:21:25.347180', NULL) RETURNING `t_student`.`id`",'time':'0.000'}

但是需要注意

1、save()方法不会被调用,所以pre_save和post_save信号不会被发送
2、多对多关系也处理不了
3、多表继承模式,不能与子模型一起工作

四、更新对象

save()默认更新所有的字段

在幕后,执行了update语句

In [1]:from crm.models import Student

In [2]:from django.db import connection

In [3]: s=Student.objects.get(id=1)

In [4]: s.age=24

In [5]: s.save()

In [6]:print(connection.queries[-1]){'sql': "UPDATE `t_student` SET `name` ='kb', `age` =24, `phone` ='15202629656', `address` = NULL, `create_time`
='2023-01-01 10:41:36.822670', `channel_id` = NULL WHERE `t_student`.`id` =1",'time':'0.047'}

save()方法默认会更新所有的字段,可以在调用save方法的时候传递参数update_fields一个字段名称列表,
这样只有列表中的字段才会被更新。优点轻微的提升性能

指定要更新的字段

**

s.save(update_fields=['age','name'])

**

In [7]: s.age=28

In [8]: s.save(update_fields=['age','name'])

In [9]:print(connection.queries[-1]){'sql':"UPDATE `t_student` SET `name` = 'kb', `age` = 28 WHERE `t_student`.`id` = 1",'time':'0.016'}

一次性更新多个对象

如果想要统一设置查询集中的所有对象的某个字段,可以使用update()方法

**

Student.objects.update(sex=1)

**

五、查询对象

1、管理器

每一个模型都有一个默认的管理器,用来操作数据表,主要是构建QuerySet
默认的管理器的名称就是objects,直接通过模型类调用。

In [19]: Student.objects
Out[19]:<django.db.models.manager.Manager at 0x18af40aa2b0>

2、QuerySet

一个QuerySet表示数据库对象的一个集合,它可以迭代可以切片可以索引(不支持负数索引)
在SQL的层面上,对应的就是select语句

3、检索全部对象

直接管理器上调用all方法

In [20]: queryset=Student.objects.all()
In [21]:type(queryset)
Out[21]: django.db.models.query.QuerySet

方法all()返回一个包含所有数据的queryset对象。
可以通过打印queryset对象的query属性,来查看当前Queryet对象将要查询的sql语句

In [23]:print(queryset.query)
SELECT `t_student`.`id`, `t_student`.`name`, `t_student`.`age`, `t_student`.`phone`, `t_student`.`address`, `t_student`.`crea
te_time`, `t_student`.`channel_id` FROM `t_student` ORDER BY `t_student`.`id` ASC

In [24]: queryset
Out[24]:<QuerySet [<Student: kb>,<Student: kobe>,<Student: li>]>

a、要注意:

Queryset对象是惰性计算的,当通过管理器创建queryset的时候,并不会直接去数据库中查询,只有真正的对queryset进行计算的时候才会到数据库中查询。
什么时候?
迭代、切片、索引、打印

4、过滤

all():方法返回所有的数据,可以通过2个方法对queryset进行过滤
filter():返回新的Queryset,包含的对象满足给定的查询条件,对应where字句的正向条件
exclude():返回一个新的Queryset,包含对象不满足对给定查询参数,对应where字句的反向条件

例如:查询所有叫kobe的学生

Student.objects.filter(name='kobe')

如果是对整个查询进行操作,all可以省略

Student.objects.all().filter(name=''kobe)

同样的

Student.objects.all().exclude(name=''kobe")
Student.objects.exclude(name=''kobe")

5、查询单个对象

filter、exclude、all返回一个queryset,即使只有一个对象满足条件,这个时候queryset只包含一个元素

如果知道只有一个对象满足查询条件,可以在管理器上使用get方法,它会直接获取这个对象

Student.objects.get(pk=2)
Student.objects.get(id=2)

get方法中的条件如果过滤出多个对象会报错
如果没有这个对象也会报错

a、first方法

获取第一个对象,
对应ASC limit 1这个子句
注意:依赖于默认的排序

**

Student.objects.first()

**

b、last方法

获取最后一个对象
对应DESC LIMIT 1这个子句

**

Student.objects.last()

**

6、排序

排序是通过在queryset上调用order_by(*fields)、默认会按照主键排序,如果模型的Meta中定义了排序规则,则默认按其排序

classMeta:
    ordering=['-c_time']        模型类中加了表示默认排序

现在在student模型上进行查询,默认会使用c_time字段的desc排序

如果要清空查询集的默认排序,可以直接在查询集上调用order_by(),不用传任何参数

**

student.objects.order_by()

**

注意:

每次在Queryset上调用order_by方法都会覆盖之前的排序

In [39]: queryset
Out[39]:<QuerySet [<Student: kb>,<Student: kobe>,<Student: li>]>

查看sql语句

**

queryset.order_by('-name','age'):按照name降序,age升序

**

In [40]: q=queryset.order_by('-name','age')

In [41]:print(q.query)
SELECT `t_student`.`id`, `t_student`.`name`, `t_student`.`age`, `t_student`.`phone`, `t_student`.`address`, `t_student`.`create_time`,
`t_student`.`channel_id` FROM `t_student` ORDER BY `t_student`.`name` DESC, `t_student`.`age` ASC

7、切片

可以使用python序列切片的语法来获取部分数据,它等价于SQL的LIMIT与OFFEST子句

**

Student.objects.all()[:5] :获取前5条数据 等价于limit 5
Student.objects.all()[2:5] :从低3条开始取3条数据,等价于 limit 3 offset 2

**

前面所有的查询中,默认都是查询所有的字段。有时候只需要查询部分字段

六、选择字段

1、values

**

queryset.values(*fields)

**

返回一个queryset,这个queryset返回一个字段列表,而不是模型对象,参数fields指定select语句中,先要查询的字段。返回的字典中只会包含我们指定的字段;
如果不指定,则包含所有字段。

例如:不指定字段,返回所有的字段

**

Student.objects.all().values()

**

In [47]: q=Student.objects.all().values()

In [49]: q
Out[49]:<QuerySet [{'id':1,'name':'kb','age':20,'phone':'15202629656','address':None,'create_time': datetime.datetime(2023,1,1,10,41,36,822670, tzinfo=<UTC>),'channel_id':None},{'id':2,'name':'kobe','age':20,'phone':None,'address':None, 'cre
ate_time': datetime.datetime(2023, 1, 1, 15, 26, 3, 84534, tzinfo=<UTC>), 'channel_id': None}, {'id': 3, 'name': 'li', 'age': 20, 'phon
e': None, 'address': None, 'create_time': datetime.datetime(2023, 1, 1, 15, 26, 3, 84534, tzinfo=<UTC>), 'channel_id':None}]>

In [50]: q[0]
Out[50]:{'id':1,'name':'kb','age':20,'phone':'15202629656','address':None,'create_time': datetime.datetime(2023,1,1,10,41,36,822670, tzinfo=<UTC>),'channel_id':None}

例如:指定字段,返回指定的字段

**

q=Student.objects.all().values('id','name')

**

In [52]: q=Student.objects.all().values('id','name')

In [53]: q
Out[53]:<QuerySet [{'id':1,'name':'kb'},{'id':2,'name':'kobe'},{'id':3,'name':'li'}]>

In [54]: q[0]
Out[54]:{'id':1,'name':'kb'}

2、value_list

**

queryset.value_list(*fields)

**

返回一个queryset,这个queryset返回一个嵌套元组的列表而不是模型对象,参数fields指定select语句中,先要查询的字段。返回的元组中只会包含我们指定的字段;
如果不指定,则包含所有字段。

例如:不指定字段,返回所有的字段

**

Student.objects.all().value_list()

**

In [3]: s=Student.objects.all()

In [7]: s2=s.values_list('name','age')

In [8]: s2
Out[8]:<QuerySet [('kb',28),('kobe',20),('li',20),('james',18),('kelai',22),('kd',19),('harden',18),('curry',22),('ad',19)]>

3、only

**

queryset.only(*fields)

**

返回queryset,这个queryset返回一个模型对象的列表。参数fields指定了我们想要查询的字段

注意:only一定会包含主键字段

q=Student.objects.all().only('name')

注意:
对only方法返回的模型对象,取没有指定的字段的值,django会再次去数据库中进行查询


In [3]: q=Student.objects.all().only('name')

In [4]: q
Out[4]:<QuerySet [<Student: kb>,<Student: kobe>,<Student: li>]>

In [5]: q[0]
Out[5]:<Student: kb>

In [6]: q[0].id
Out[6]:1

In [7]: q[0].name
Out[7]:'kb'

In [8]: q[0].age
Out[8]:20

In [9]:print(connection.queries[-1]){'sql': 'SELECT `t_student`.`id`, `t_student`.`age` FROM `t_student` WHERE `t_student`.`id` =1 LIMIT
21', 'time': '0.015'}

In [10]: q
Out[10]:<QuerySet [<Student: kb>,<Student: kobe>,<Student: li>]>

In [11]:print(connection.queries[-1]){'sql': 'SELECT `t_student`.`id`, `t_student`.`name` FROM `t_student` ORDER BY `t_student`.`id` ASC LI
MIT 21', 'time': '0.000'}

4、defer

**

defer(*fields)

**

q=Student.objects.all().defer('create_time')

defer方法中的参数fields指定了select语句中想要排除的查询字段,其他与only相同;
返回queryset,这个queryset返回一个模型对象的列表。

In [12]: q=Student.objects.all().defer('create_time')

In [13]: q
Out[13]:<QuerySet [<Student: kb>,<Student: kobe>,<Student: li>]>

In [14]:print(connection.queries[-1]){'sql': 'SELECT `t_student`.`id`, `t_student`.`name`, `t_student`.`age`, `t_student`.`phone`, `t_stude
nt`.`address`, `t_student`.`channel_id` FROM `t_student` ORDER BY `t_student`.`id` ASC LIMIT 21', 'tim
e': '0.016'}

In [16]: q[0].create_time
Out[16]: datetime.datetime(2023,1,1,10,41,36,822670, tzinfo=<UTC>)

注意

only与defer返回的对象还是可以正常访问没有包含select语句中的字段,只是再次查询数据库

七、条件查询

在filter,exclude、get中可以接收参数,实现各种条件的查询

1、exact(精确匹配)、iexact(精确匹配,不区分大小写)

Student.objects.get(qq__exact=88888)
Student.objects.get(qq=88888)    简写

qq_exact=66666等价与qq=66666
默认情况下这个__exact省略
对应where语句中的相等条件

In [18]: Q=Student.objects.only('name').filter(name__iexact='KOBE')

In [20]:print(Q.query)
SELECT `t_student`.`id`, `t_student`.`name` FROM `t_student` WHERE `t_student`.`name` LIKE KOBE ORDER
BY `t_student`.`id` ASC

2、in

在一个给定的可迭代对象中,通常是一个列表,元组或者queryset

**

Student.objects.filter(age__in=[18,20])

**
对应where字句中的in

In [22]: q=Student.objects.filter(age__in=[18,20])

In [23]:print(q.query)
SELECT `t_student`.`id`, `t_student`.`name`, `t_student`.`age`, `t_student`.`phone`, `t_student`.`addr
ess`, `t_student`.`create_time`, `t_student`.`channel_id` FROM `t_student` WHERE `t_student`.`age` IN
(18,20) ORDER BY `t_student`.`id` ASC

3、range

范围区间
对应sql中的between and

**

Student.objects.filter(age__range=[10,25])

**

4、gt、gte、lt、lte

gt:大于
gte:大于等于
lt:小于
lte:小于等于

**

Student.objects.filter(age__gt=18)

**

八、条件组合

1、AND

以下都是相同操作

Student.objects.filter(name='kobe',age=18)
Student.objects.filter(name='kobe').filter(age=18)
Student.objects.filter(name='kobe')& Student.objects.filter(age=18)from django.db.model import Q
Student.objects.filter(Q(name='kobe')& Q(age=18))

等价于sql
where name= AND age=

2、OR

from django.db.model import Q

Student.objects.filter(name='kobe')| Student.objects.filter(age=18)
Student.objects.filter(Q(name='kobe')| Q(age=18))

等价于sql
where name= OR age=

九、聚合查询

需要导入:from django.db.models import Count,Sum,Avg,Max,Min

Count:统计数量

q8=Student.objects.aggregate(Count('id'))print(q8)

返回一个字典 {‘id__count’: 3}

可以指定聚合字段的值

q9=Student.objects.aggregate(count=Count('id'))print(q9)

返回一个字典 {‘count’: 3}

Sum:求和
Avg:求平均值
Max:求最大值
Min:求最小值

可以直接在查询集上调用count方法,会返回这个查询集的统计数量

**

q=Student.objects.count()

**

十、分组查询

一般分组会和聚合结合使用
django中需要使用values,annotate和聚合方法结合使用,

案例:
查询男女生各有多少人

Student.objects.values('sex').annotate(Count('sex'))

注意:

annotate默认使用主键进行分组
使用values时,要提前清空查询集上的order_by,不然结果是意料之外的

十一、删除对象

In [9]: s=Student.objects.get(id=1)

In [10]: s.delete()
Out[10]:(1,{'crm.Student':1})

在这里插入图片描述

标签: django python 后端

本文转载自: https://blog.csdn.net/YZL40514131/article/details/128569190
版权归原作者 敲代码敲到头发茂密 所有, 如有侵权,请联系我们删除。

“【django】模型类中数据的增删改查操作总结”的评论:

还没有评论