Django ORM 操作
Django ORM操作
最常用的ORM方法
| 方法 | 描述 | |
|---|---|---|
| all() | 返回所有结果 | 返回QuerySet对象 |
| get(**kwargs) | 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误 | 返回具体对象 |
| filter(**kwargs) | 它包含了与所给筛选条件相匹配的对象 | 返回QuerySet对象 |
| exclude(**kwargs) | 它包含了与所给筛选条件不匹配的对象 | 返回QuerySet对象 |
| values(*field) | 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列 | 返回一个可迭代的字典序列 |
| values_list(*field) | 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列 | 返回一个可迭代的元祖序列 |
| order_by(*field) | 对查询结果排序 | 返回QuerySet对象 |
| reverse() | 对查询结果反向排序,请注意reverse()通常只能在具有已定义顺序的QuerySet上调用(在model类的Meta中指定ordering或调用order_by()方法) | 返回QuerySet对象 |
| distinct() | 从返回结果中剔除重复纪录(如果你查询跨越多个表,可能在计算QuerySet时得到重复的结果。此时可以使用distinct(),注意只有在PostgreSQL中支持按字段去重。) | 返回QuerySet对象 |
| count() | 返回数据库中匹配查询(QuerySet)的对象数量。 | 返回数值 |
| first() | 返回第一条记录 | 返回具体对象 |
| last() | 返回最后一条记录 | 返回具体对象 |
| exists() | 如果QuerySet包含数据,就返回True,否则返回False | 返回布尔值 |
单表查询之神奇的双下划线
| 举例 | 解释 |
|---|---|
objects.filter(id__in=[11, 22, 33]) |
获取id等于11、22、33的数据 |
objects.exclude(id__in=[11, 22, 33]) |
获取id not in 11,22,33的数据 |
objects.filter(name__contains="ven") |
获取name字段包含”ven”的 |
objects.filter(name__icontains="ven") |
icontains大小写不敏感 |
objects.filter(id__range=[1, 3]) |
id范围是1到3的 |
objects.filter(first_day__year=2017) |
first_day字段为2017年的数据 |
objects.filter(brith_year=2018,name_contains='ve') |
包含’ve’的name且birth为2018年的数据 |
objects.filter(name__isstartwith="ven") |
True/False |
objects.filter(name__startwith="ven") |
获取name以ven开头的数据 |
objects.filter(name__isendswith="ven") |
True/False |
objects.filter(name__endswith="ven") |
获取name以ven结尾的数据 |
objects.filter(id__lt=10, id__gt=1) |
获取id大于1 且 小于10的值 |
外键操作
1 | from django.db import models |
正向查找:多对一(设置了foreignKey一方开始查找另一表)
1 | # 通过对象查找(跨表) ==> 对象.外键关联字段.字段 |
反向查找:一对多
1 | # 对象查找 ==> obj.表名_set 注:表名小写_set 即关联到对应表 |
多表查询之ManyToManyField
“关联管理器” 是在一对多或者多对多的关联上下文中使用的管理器。
它存在于下面两种情况:
外键关系的反向查询
多对多关联关系
简单来说就是当 点后面的对象 可能存在多个的时候就可以使用以下的方法。
1 | create() # ==> 返回新创建的对象 |
- 对于外键对象,clear()和remove() 方法仅在null=True时存在。
- 对于所有类型的关联字段,add()、create()、remove()、clear() 、set() 都会马上更新数据库,换句话说,在关联的任何一端,都不需要再调用save()方法。
- 对于改变单表未关联其它表的字段,需要使用save()一下。
per_obj.name = new_name
per_obj.save()
聚合查询和分组查询
聚合查询:即mysql中的聚合函数sum(),count(),avg()…
aggregate()是querySet的一个终止子句,意思即,它返回一个包含一些键值对的字典。
键的名称是聚合值的标识符,值是计算出来得聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。
1 | from django.db.models import Avg,Sum,Max,Min,Count |
分组:即mysql中的group_by,使用annotate()方法
1 | from django.db.models import Avg |
统计每一本书的作者个数
1 | book_list = models.Book.objects.all().annotate(author_num=Count('author')) |
统计出每个出版社买的最便宜的书的价格
1 | > # 正向 |
统计不止一个作者的图书
1 | models.Book.objects.annotate(author_num=Count('author')).filter(author_num__gt=1) |
根据一本图书作者数量的多少对查询集QuerSet进行排序
1 | models.Book.objects.annotate(author_num=Count('author')).order_by('author_num') |
查询各个作者出的书的总价格
1 | models.Author.objects.annotate(sum_price=Sum('book__price')).values('name','sum_price') |
F查询和Q查询
F查询
Django提供F()方法来做这样的比较
F()的实例可以在查询中引用字段,来比较同一个model实例中两个不同字段的值。
查询评论数大于收藏数的书籍
1 | from django.db.models import F |
详解增加表数据
1 | # save 方法增加数据 |
注意:update方法更新数据修改不能用get的原因是:update是QuerySet对象的方法,get返回的是一个具体model对象,它没有update方法
而filter返回的是一个QuerySet对象(filter里面的条件可能有多个条件符合,比如name=’jony’,可能有两个name=’jony’的行数据)。
models模型的save()方法,这个方法会更新一行里的所有列。 而某些情况下,我们只需要更新行里的某几列,update效率更高。
此外,update()方法对于任何结果集(QuerySet)均有效,这意味着你可以同时更新多条记录update()方法会返回一个整型数值,表示受影响的记录条数。
注意,这里因为update返回的是一个整形,所以没法用query属性;对于每次创建一个对象,想显示对应的raw sql,需要在settings加上日志记录部分
Q查询
filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR 语句),你可以使用Q 对象。
查询id大于1并且评论数大于100的书
1 | models.Book.objects.filter(nid__gt=1,commentNum__gt=100) |
查询评论数大于100或者阅读数小于200的书
1 | # Q 对象可以使用& 和| 操作符组合起来。当一个操作符在两个Q 对象上使用时,它产生一个新的Q 对象。 |
查询年份等于2017年或者价格大于200的书
1 | models.Book.objects.filter(Q(publishDdata__year=2017)|Q(price__gt=200)) |
查询年份不是2017年或者价格大于200的书
1 | models.Book.objects.filter(~Q(publishDdata__year=2017)&Q(price__gt=200)) |
查询函数可以混合使用
Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q对象)都将”AND”在一起。但是,如果出现Q对象,它必须位于所有关键字参数的前面。例如:
1 | bookList=models.Book.objects.filter(Q(publishDateyear=2016) | Q(publishDateyear=2017),title__icontains="python") |
ORM表自关联
内自关联是指表内数据相关联的对象和表是相同字段,这样我们就直接用表内关联将外键关联设置成自身表的字段。同样表内关联也分一对多字段和多对多字段
创建自关联表(一对多情景)
1 | # 对于微博评论,每条评论都可能有子评论,但每条评的字段内容应该都是相同的,并且每条评论都只有一个父评论,这就满足了,一对多的情形。父评论为关联字段,可以对应多个子评论,这就是一对多的自关联。 |
添加数据,第一条数据关联字段为空,说明是父评论
第二条数据关联了第一条数据说明是第一条数据的字评论,同样后两条数据是是第二条数据的子评论
| id | content | push_time | pcomment_id |
|---|---|---|---|
| 1 | 你好啊 | 2019-08-10 06:25:33 | Null |
| 2 | 兄弟你好 | 2019-08-10 06:26:13 | 1 |
| 3 | 老虎,你先上 | 2019-08-10 06:25:53 | 2 |
| 4 | 跟老虎还称兄道弟 | 2019-08-10 06:27:33 | 2 |
通过筛选父评论关联字段等于1的对象
1 | Comment.objects.filter(pcomment_id=1) |
根据子评论关联id正在查找父评论的内容
1 | Comment.objects.filter(pcomment_id=2).values('pcomement__content') |
根据父评论的id 反向查找子评论
1 | Comment.objects.filter(id=1).values('comment__id'') |
注意:外键关联是在子评论中,有关联字段的是子评论,子评论查父评论是正向,父评论查子评论是反向。
多对多表自关联
1 | # 建立一张表,表字段为姓名以及朋友多对多字段,一个人可有多个朋友,也可以是多个人的朋友,找一个人的朋友是正向查找,找是某个人的朋友是反向查找。 |
正向查找关联字段__name 查找沁阳的基友
1 | Person.objects.filter(name='沁阳').values('friends__name') |
反向查找 沁阳的基友
1 | Person.objects.all().filter(ship__name='沁阳') |
正向查找 王帅的朋友
1 | Person.objects.get(name='王帅').friends.all() |
反向查找 是王帅朋友的人
1 | Person.objects.filter(ship__name='王帅') |
基友是沁阳的那个人反向查找
1 | Person.objects.get(name='沁阳').ship.all() |
基友是王帅的那个人反向查找
1 | Person.objects.get(name='王帅').ship.all() |
基友含有沁阳的人反向
1 | Person.objects.filter(name='沁阳').values('ship__name') |
注意:查找某人的朋友是正向,查找朋友里面有某人的人是反向查找
Django终端打印SQL语句
1 | # 在Django项目的settings.py文件中,在最后复制粘贴如下代码: |
在Python脚本中调用Django环境
1 | # 在应用的目录下建立一个py文件,将下面的代码写入 |
参考:ORM操作
ORM表自关联

