天天看点

django ORM之CRUD基本、进阶、高阶操作

django的orm是一个十分强大的数据库操作模块,用面对对象的思想为我们重构了sql查询语句,一个类就代表一个表,一个属性就代表一个字段。极大的简化了我们对数据库操作的复杂度。

数据库操作无外乎CRUD这一套操作,即增、查、改、删。

ORM基本的增删改查:

增:

modes.Tb.object.create() # 增加一条数据,可以接受字典(**kwargs)类型的数据

obj = modes.Tb()
obj.save() # 可批量添加数据
           

查:

models.Tb.objects.get() # 获取单条数据,不存在报错
models.Tb.objects.all() # 获取全部数据
models.Tb.objects.filter() # 获取指定条件的数据,不存在返回None
           

改:

models.Tb.objects.filter().update() # 将指定条件的数据更新,支持**kwargs
# update更新完保存到数据库不会执行save()方法,因此不会更新auto_now设置的字段
obj = models.Tb.objects.get()
obj.c1 = " "
obj.save()
           

删:

ORM之进阶操作(双下划线的魅力):

获取个数:

gt(大于),gte(大于等于),lt(小于),lte(小于等于):

id__gt = 1 # 获取id大于1的数据
id__gte = 1 # 获取id大于等于1 的数据
id__lt = 10 # 获取id小于10的数据
id__ite = 10 # 获取id小于等于10的数据
id__lt = 10,id__gt = 1 #获取id大于1且小于10的数据
           

in:

id__in = [1,2,3] # 获取id等于1,2,3的数据
exclude(id__in = [1,2,3]) # 获取id不等于1,2,3的数据
           

isnull(是否为空):

contains:

name__contains = "××" # 获取名字包含××的数据
name__icontains = "××" # 同样是获取名字包含××的数据,但对大小写不敏感
exclude(name__icontains = " ××") # 获取名字不包含××的数据
           

range:

还有一些其他类似的方法:

startwswith(判断开头),istartswith(不区分大小写),endswith(判断结尾),iendswith(不区分大小写)。

order_by:

filter().order_by("id") # 以id为标准进行正向排序
filter().order_by("-id") # 反向排序
           

group_by:

limit(限制个数),offset(偏移量)(切片操作):

regex(正则匹配):

title__regex = r'^\d+' # 获取标题开头为数字的数据
iregex不区分大小写
           

ORM之高阶操作:

values:

指定需要提取的字段,默认全部提取,返回的是字段和值组成的字典

objects.values("字段")
# 如果想要更改字段名,可以使用关键字参数
objects.values(new_name = F("字段")) # new_name不可与表中已有名字冲突
           
django ORM之CRUD基本、进阶、高阶操作
django ORM之CRUD基本、进阶、高阶操作

values中还可以使用聚合函数形成新的字段。

values_list:

同values功能一样,只不过返回的是字段和值组成的元组

django ORM之CRUD基本、进阶、高阶操作

defer:

过滤掉不需要的字段,返回的是queryset对象模型

django ORM之CRUD基本、进阶、高阶操作

only:

与defer相反,获取需要的字段。

get_or_create:

根据条件进行查找,如果找到了就返回,没找到就创建一个再返回,例如我们去获取一个文章的作者时,如果没有就创建一个作者“佚名”并返回。

django ORM之CRUD基本、进阶、高阶操作

bulk_create:

一次性创建多条数据

distinct:

去除掉重复数据

需要注意的是,如果在distinct之前使用了order_by,那么因为order_by会提取order_by中指定的字段,因此再使用distinct就会根据多个字段来进行唯一化,所以就不会把那些重复的字段删掉。

F:

用来更新获取原来值的,例如F(age)表示原age

Q:

filter(Q(id=1) | Q(id=2)) # 获取id=1或id=2的数据,“|”表示或
filter(Q(id=1) & Q(id=2)) # 获取id=1和id=2的数据,“&”表示与

# 另一种用法
# q1 里的条件均为or的关系
q1 = Q()
q1.connector = "OR" # 限定关系为or
q1.children.append(("id",1)) # 添加限定条件
q1.children.append(("id",2)) 
# q2里的条件也均为or的关系
q2 = Q()
q2.connector = "OR"
q2.children.append(("age",18))
q2.children.append(("age",19))
# 使用connect通过and的条件将q1和q2联系到一块
connect = Q()
connect.add(q1,"AND")
connect.add(q2,"AND")
# 上面的语句得到的结果就是获取id为1 或 id为2 和 age为18 或 age为19 的数据
# Q用于构造较为复杂的查询条件。
           

extra:

可以用来执行原生的sql语句

#参数有:select=None, where=None, params=None, tables=None, order_by=None, select_params=None

models.Tb.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])
           

还有一种直接执行原生sql的方法:raw()

#参数:raw_query, params=None, translations=None, using=None

models.UserInfo.objects.raw('select * from userinfo')
           

select_related:

只可用于一对多或一对一关系中

prefetch_related:

主要用于多对一或者多对多关系中,也可用于一对一或一对多