一、什么是Django ORM
ORM--(Object Relational Mapping)关系对象映射
QuerySet表示数据库中的对象集合。可以有0、1或多个过滤器,在SQL中,QuerySet等于SELECT语法过滤器是限制子句,如WHERE或LIMIT
那么怎么查看所执行的SQL语句呢,query.__str__()
,或者print(QuerySet.query)
In [1]:Teacher.objects.all().query.__str__()
Out[1]: 'SELECT `teacher`.`id`, `teacher`.`name` FROM `teacher`'
二、基础操作(增删改查)
2.1、增
取对象,赋值然后,save()
>>> from school.models import *
>>> teacher = Teacher()
>>> teacher.name = "懒得卡"
>>> teacher.save()
2.2、删
delete()
,批量删除就查询再删除
>>> Teacher.objects.get(pk=1).delete()
2.3、改
改得话有两种,取到具体某一个QuerySet对象,重新赋值然后save()
,第二种就是查询后update(key="newvalue")
2.4、查
2.4.1、基础查询
-
检索所有对象
all()
方法>>> Teacher.objects.all()
-
检索特定对象
filter()
返回QuerySet包含与给定查找条件匹配的新对象,是一个类似于列表的类型,所以只存在单个元素时候,也需要取索引.
exclude()
返回QuerySet包含与查找条件不匹配的新对象 -
检索单个对象
get()
如果没有查询匹配的结果,get()则会引发DoseNotExist异常,有多个结果也会返回ObjectReturned异常 -
字段查找
精确匹配:
__exact = "匹配内容"
,无实际作用忽略大小写匹配:
__iexact = "匹配内容"
包含匹配条件:
__contains = "匹配内容"
, 同样的也有icontains
模糊匹配:
__startswith = "以内容开头"
,__endswith = "以内容结尾"
,同样有忽略大小写的,在前面加i
就行正则匹配:
__regex ="r'正则表达式匹配内容'"
,忽略大小写iregex
比较匹配: 大于
__gt
,小于__lt
,大于等于__gte
,小于等于__lte
__in = ["true","false","hahah"]
和__range(1,3)
范围获取默认为空/不为空的字段:
__isnull = True/False
-
跨越关系的查找
使用跨模型的相关字段,直接使用字段名称,用双下划线分割,可多次使用
要使用"反向"关系,只需要使用模型的小写名称即可. -
F查询(解决字段之间匹配的问题)
>>> from django.db.models import F >>> # e.g. 要查找作者姓名和博客名称相同的所有条目 >>> Entry.objects.filter(author__name=F('blog__name'))
F对象支持+ , - , * , / , %(模运算,求余), ^(幂运算)和跨越关系等
>>> e.g. 查找点赞数大于评论加收藏数的所有条目 >>> Entry.objects.filter(goods__gt=F('comments')+F('collect'))
对于日期和时间型的字段,可以用timedelta对象来实现加减
>>> from datetime import timedelta >>> e.g. 查找发布时间超过3天的文章 >>> Entry.objects.filter(date__gt=F('pub_date')+timedelta(day=3))
-
Q查询(解决"或"的问题)
& , | , ~ 运算符,在两个Q对象上使用与或非运算符时,它会产生一个新的Q对象>>> from django.db.models import Q >>> Q(question__startswith="who") | Q(question__startswith="what")
2.4.2、聚合(Aggretations)
Django提供了两种生成聚合的方法
-
aggregate()聚合
常见的聚合函数有Avg/Count/Sum/Max/Min等等>>> from django.db.models import Count >>> Entry.objects.all().aggregate(num_books=Count("book")).values("num_books") { 'num_books':27 } >>> # 这里的all()可以省略掉,就变成了 >>> Entry.objects.aggregate(num_books=Count("book")).values("num_books") >>> # num_books为别名,类似于SQL里面的as
aggregate()支持在聚合函数内内联Q查询
>>> e.g. 统计整个班男生和女生的数量(gender为0为男生,1为女生) >>> Student.objects.aggregate(mail=Count("gender",filter=Q(gender=0)),famail=Count("gender",filter=Q(gender=1)))
-
annotate()分组
分组和MySQL中的分组不太一样,它默认对所用对象的id进行分组,比如Student.objects.annotate(...)
就是将学生按学生id进行分组了已经.同样的,分组一定要进行聚合操作</br>
所以在反复练习之后,对用那个对象进行查询就很明显了,例如查询AAA大于/小于/其他条件的BBB的CCC项
那就是使用BBB的对象了,BBB.objects.(...)
-
order_by()排序
排序也没要多的需要讲的,order_by("-name")
降序,默认排序方式为由低到高 -
values()/values_list() 获取查询结果的某一或者某些列,
values_list
获取的值为一个元组 -
distinct() 从返回结果中剔除重复记录.这个不属于聚合,但是在学习这些的时候遇到了
网友评论