<1> all(): 查询全部结果 <2> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 <3> get(**kwargs): 返回与所给筛选条件相匹配的对象 返回结果有且只有一个,若是符合筛选条件的对象超过一个或者没有都会抛出错误。 <4> exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象 <5> values(*field): 返回一个ValueQuerySet, 运行后获得的不是一系列model的实例化对象,而是一个可迭代的字典序列 <6> values_list(*field): 它与values()很是类似,它返回的是一个元组序列,values返回的是一个字典序列 <7> order_by(*field): 对查询结果排序 <8> reverse(): 对查询结果反向排序,请注意reverse()一般只能在具备已定义顺序的QuerySet上调用 (在model类的Meta中指定ordering或调用order_by()方法)。 <9> distinct(): 从返回结果中剔除重复纪录 (若是你查询跨越多个表,可能在计算QuerySet时获得重复的结果此时可使用distinct(), 注意只有在PostgreSQL中支持按字段去重。) <10> count(): 返回数据库中匹配查询(QuerySet)的对象数量。 <11> first(): 返回第一条记录 .all().first 等效于 .first() <12> last(): 返回最后一条记录 <13> exists(): 若是QuerySet包含数据,就返回True,不然返回False
all() filter() exclude() order_by() reverse() distinct()
values() 返回一个可迭代的字典序列 values_list() 返回一个可迭代的元祖序列
具体的对象是没法使用这两个方法的 原理上来讲models.py 里面的 class类 中就没有 这两个属性 这两个属性只针对于一个QuerySet序列集进行筛选才可使用 好比 .filter(id=1) 虽然只返回了一个QuerySet对象 可是也可使用
get() first() last()
对象能够直接 .属性 的方法去取值 原理上来讲在数据库对象的里面就有属性天然是能够知己调用的
exists()
count()
具体对象python
QuerySet对象linux
转换sql
QuerySet对象------>具体对象数据库
QuerySet对象.first()django
QuerySet对象[0]缓存
# 查询 "部门表" 的所有内容 # 查询的时候不带 values或者values_list 默认就是查询 all() ret = models.Employee.objects.all() # """ # SELECT `employee`.`id`, `employee`.`name`, `employee`.`age`, `employee`.`salary`, `employee`.`province`, `employee`.`dept` FROM `employee` LIMIT 21; args=() # """ # 查询全部人的 "部门" 和 "年龄" # values 或者 values_list 里面写什么就至关于 select 什么字段 ret = models.Employee.objects.all().values("dept", "age") # """ # SELECT `employee`.`dept`, `employee`.`age` FROM `employee` LIMIT 21; args=() # """
models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于十一、2二、33的数据 models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in models.Tb1.objects.filter(name__contains="ven") # 获取name字段包含"ven"的 models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 models.Tb1.objects.filter(id__range=[1, 3]) # id范围是1到3的,等价于SQL的bettwen and 左右都包含 # 相似的还有:startswith,istartswith, endswith, iendswith # date字段还能够单独将年月日拿出来 models.Class.objects.filter(birtday__year=2017) models.Class.objects.filter(birtday__month=7) models.Class.objects.filter(birtday__day=17)
正向查询,按字段app
book_obj.publish : 与这本书关联的出版社对象
book_obj.publish.addr: 与这本书关联的出版社的地址
反向查询,按表名_setide
publish_obj.book_set: 与这个出版社关联的书籍对象集合
publish_obj.book_set.all() :[obj1,obj2,....]
正向查询,按字段函数
author_obj.ad : 与这个做者关联的做者详细信息对象
反向查询:按表名fetch
author_detail_obj.author : 与这个做者详细对象关联的做者对象
正向查询,按字段
book_obj.authorList.all(): 与这本书关联的全部这做者对象的集合 [obj1,obj2,....] book_obj.authorList.all().values("name"): 若是想查单个值的时候能够这样查
反向查询,按表名_set
author_obj.book_set.all() : 与这个做者关联的全部书籍对象的集合 book_obj.book_set.all().values("name"): 若是想查单个值的时候能够这样查
正向查询,按字段
# 查询linux这本书的出版社的名字: models.Book.objects.all().filter(title="linux").values("publish__name")
反向查询:按表名
# 查询人民出版社出版过的全部书籍的名字 models.Publish.objects.filter(name="人民出版社出版").values("book__title")
正向查询,按字段
#查询egon的手机号 models.Author.objects.filter(name="egon").values("ad__tel")
反向查询:按表名
#查询手机号是151的做者 models.AuthorDetail.objects.filter(tel="151").values("author__name")
正向查询,按字段
#查询python这本书的做者的名字 models.Book.objects.filter(title="python").values("authorList__name") [{},{},{},{}]
反向查询,按表名
#查询alex出版过的出的价格 models.Author.objects.filter(name="alex").values("book__price")
ps:
若是哟有设置,反向查询的时候都用:related_name 的值
publish=models.ForeignKey("Publish",related_name="bookList") authorlist=models.ManyToManyField("Author",related_name="bookList") ad=models.models.OneToOneField("AuthorDetail",related_name="authorInfo")
利用 关联管理器 进行维护
建立一个新的对象,保存对象,并将它添加到关联对象集之中,返回新建立的对象。
models.Author.objects.first().book_set.create(title="羊驼之歌", publish_id=2)
把指定的model对象添加到关联对象集中。
添加对象 >>> author_objs = models.Author.objects.filter(id__lt=3) >>> models.Book.objects.first().authors.add(*author_objs)
添加id >>> models.Book.objects.first().authors.add(*[1, 2])
更新model对象的关联对象。
book_obj = models.Book.objects.first() book_obj.authors.set([2, 3])
从关联对象集中移除执行的model对象
book_obj = models.Book.objects.first() author_obj.books.remove(book_obj) author_obj.books.remove(8) # 把id = 8 的书删掉
从关联对象移除一切对象。
book_obj = models.Book.objects.first() book_obj.authors.clear()
注意:
对于ForeignKey对象,clear()和remove()方法仅在null=True时存在。
# ForeignKey字段没设置null=True时, class Book(models.Model): title = models.CharField(max_length=32) publisher = models.ForeignKey(to=Publisher) # 没有clear()和remove()方法: >>> models.Publisher.objects.first().book_set.clear() Traceback (most recent call last): File "<input>", line 1, in <module> AttributeError: 'RelatedManager' object has no attribute 'clear' # 当ForeignKey字段设置null=True时, class Book(models.Model): name = models.CharField(max_length=32) publisher = models.ForeignKey(to=Class, null=True) # 此时就有clear()和remove()方法: dels.Publisher.objects.first().book_set.clear()
注意
对于全部类型的关联字段,add()、create()、remove() 和 clear(), set() 都会立刻更新数据库。
换句话说,在关联的任何一端,都不须要再调用save()方法。
1 from django.shortcuts import render,HttpResponse 2 3 # Create your views here. 4 5 6 from app01 import models 7 8 def query(request): 9 10 # #####################基于对象查询(子查询)############################## 11 # 按字段(publish) 12 # 一对多 book -----------------> publish 13 # <---------------- 14 # book_set.all() 15 16 # 正向查询按字段: 17 18 # 查询python这本书籍的出版社的邮箱 19 20 # python=models.Book.objects.filter(title="python").first() 21 # print(python.publish.email) 22 23 24 # 反向查询按 表名小写_set.all() 25 26 # 苹果出版社出版的书籍名称 27 28 # publish_obj=models.Publish.objects.filter(name="苹果出版社").first() 29 # for obj in publish_obj.book_set.all(): 30 # print(obj.title) 31 32 # 按字段(authors.all()) 33 # 多对多 book -----------------------> author 34 # <---------------- 35 # book_set.all() 36 37 38 # 查询python做者的年龄 39 # python = models.Book.objects.filter(title="python").first() 40 # for author in python.authors.all(): 41 # print(author.name ,author.age) 42 43 # 查询alex出版过的书籍名称 44 45 # alex=models.Author.objects.filter(name="alex").first() 46 # for book in alex.book_set.all(): 47 # print(book.title) 48 49 # 按字段 authorDetail 50 # 一对一 author -----------------------> authordetail 51 # <---------------- 52 # 按表名 author 53 54 55 #查询alex的手机号 56 # alex=models.Author.objects.filter(name='alex').first() 57 # print(alex.authorDetail.telephone) 58 59 60 # 查询家在山东的做者名字 61 62 # ad_list=models.AuthorDetail.objects.filter(addr="shandong") 63 # 64 # for ad in ad_list: 65 # print(ad.author.name) 66 67 68 69 ''' 70 对应sql: 71 72 select publish_id from Book where title="python" 73 select email from Publish where nid = 1 74 75 76 ''' 77 78 79 80 81 # #####################基于queryset和__查询(join查询)############################ 82 83 # 正向查询:按字段 反向查询:表名小写 84 85 86 # 查询python这本书籍的出版社的邮箱 87 # ret=models.Book.objects.filter(title="python").values("publish__email") 88 # print(ret.query) 89 90 ''' 91 select publish.email from Book 92 left join Publish on book.publish_id=publish.nid 93 where book.title="python" 94 ''' 95 96 # 苹果出版社出版的书籍名称 97 # 方式1: 98 ret1=models.Publish.objects.filter(name="苹果出版社").values("book__title") 99 print("111111111====>",ret1.query) 100 #方式2: 101 ret2=models.Book.objects.filter(publish__name="苹果出版社").values("title") 102 print("2222222222====>", ret2.query) 103 104 #查询alex的手机号 105 # 方式1: 106 ret=models.Author.objects.filter(name="alex").values("authorDetail__telephone") 107 108 # 方式2: 109 models.AuthorDetail.objects.filter(author__name="alex").values("telephone") 110 111 # 查询手机号以151开头的做者出版过的书籍名称以及书籍对应的出版社名称 112 113 ret=models.Book.objects.filter(authors__authorDetail__telephone__startswith="151").values('title',"publish__name") 114 print(ret.query) 115 116 117 return HttpResponse("OK")
惰性执行
books = BookInfo.objects.all() # 此时,数据库并不会进行实际查询 # 只有当真正使用时,如遍历的时候,才会真正去数据库进行查询 for b in books: print(b)
缓存
# 进行数据库实际查询遍历,保存结果到bs,会进行数据库实际交互 bs = [b.id for b in BookInfo.objects.all()] # 再次调用缓存结果bs,再也不进行数据库查询,而是使用缓存结果
exists()
简单的使用if语句进行判断也会彻底执行整个queryset而且把数据放入cache,虽然你并不须要这些数据!为了不这个,能够用exists()方法来检查是否有数据:
if queryResult.exists(): #SELECT (1) AS "a" FROM "blog_article" LIMIT 1; args=() print("exists...")
iterator()
当queryset很是巨大时,cache会成为问题。
处理成千上万的记录时,巨大的queryset可能会锁住系统进程,让你的程序濒临崩溃。
要避免在遍历数据的同时产生queryset cache,可使用 iterator() 方法 来获取数据,处理完数据就将其丢弃
objs = Book.objects.all().iterator() # iterator()能够一次只从数据库获取少许数据,这样能够节省内存 for obj in objs: print(obj.title) # 基于迭代器的特性,被遍历到底部以后下次在使用是无效的了。 for obj in objs: print(obj.title)
使用 .iterator() 来防止生成cache,意味着遍历同一个queryset时会重复执行查询.
因此使 用 .iterator() 时需确保操做一个大queryset时没有重复执行查询.
Queryset的cache是用于减小程序对数据库的查询,在一般的使用下会保证只有在须要的时候才会查询数据库。
使用exists()和iterator()方法能够优化程序对内存的使用。不过,因为它们并不会生成queryset cache,可能 会形成额外的数据库查询。
from django.db.models import Avg, Sum, Max, Min, Count
>>> from django.db.models import Avg, Sum, Max, Min, Count >>> models.Book.objects.all().aggregate(Avg("price")) {'price__avg': 13.233333}
# 指定名称 >>> models.Book.objects.aggregate(average_price=Avg('price')) {'average_price': 13.233333} # 屡次聚合 >>> models.Book.objects.all().aggregate(Avg("price"), Max("price"), Min("price")) {'price__avg': 13.233333, 'price__max': Decimal('19.90'), 'price__min': Decimal('9.90')}
aggregate 返回的是一个字典,而不是queryset 对象
Employee.objects.values("dept").annotate(avg=Avg("salary").values(dept, "avg")
# 每一个 “省” 的 “平均工资” , 查询后的结果为 “省 : 平均工资 ” # annotate前面是什么就按照什么来分组,annotate后面的字段是被分组后被计算的新增数据列, ret = models.Employee.objects.values("province").annotate(a=Avg("salary")).values("province", "a") # """ # SELECT `employee`.`province`, AVG(`employee`.`salary`) AS `a` FROM `employee` GROUP BY `employee`.`province` ORDER BY NULL LIMIT 21; args=() # """
# 统计每一本书的做者个数 book_list = models.Book.objects.all().annotate(author_num=Count("author")) # 统计出每一个出版社买的最便宜的书的价格 publisher_list = models.Publisher.objects.annotate(min_price=Min("book__price")) publisher_list = models.Book.objects.values("publisher__name").annotate(min_price=Min("price")) # 统计不止一个做者的图书 book_list = models.Book.objects.annotate(author_num=Count("author")).filter(author_num__gt=1) # 根据一本图书做者数量的多少对查询集 QuerySet进行排序 book_list = models.Book.objects.annotate(author_num=Count("author")).order_by("author_num") # 查询各个做者出的书的总价格 author_list = models.author.annotate(sum_price=Sum("book__price")).values("name", "sum_price"))
# ORM连表分组查询 # 根据 "部门" 计算出 "平均工资" 结果为显示为 "部门名字 : 平均工资" 的表 ret = models.Person.objects.values("dept_id").annotate(a=Avg("salary")).values("dept__name", "a") # """ # SELECT `dept`.`name`, AVG(`person`.`salary`) AS `a` FROM `person` INNER JOIN `dept` ON (`person`.`dept_id` = `dept`.`id`) GROUP BY `person`.`dept_id`, `dept`.`name` ORDER BY NULL LIMIT 21; args=() # """
查询每一个部门的员工的员工数
查询每一个部门的员工总工总人数
对于基础的两个值得比较能够经过上面的方法实现
可是对于两个字段的比较则须要用到 F 查询
# 查询评论数大于收藏数的书籍 from django.db.models import F models.Book.objects.filter(commnet_num__gt=F('keep_num')) # Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操做。 models.Book.objects.filter(commnet_num__lt=F('keep_num')*2) # 对整个字段的全部值的操做也能够经过 F 函数实现 # 好比将每一本书的价格提升30元 models.Book.objects.all().update(price=F("price")+30)
关于修改 char 字段的操做
# 把全部书名后面加上(初版) >>> from django.db.models.functions import Concat >>> from django.db.models import Value >>> models.Book.objects.all().update(title=Concat(F("title"), Value("("), Value("初版"), Value(")")))
当使用filter 的时候 ,内部多个筛选条件是 and 的关系
若需求为 or 的关系须要用到 Q 查询
# 查询做者名是羊驼或山羊的 models.Book.objects.filter(Q(authors__name="羊驼")|Q(authors__name="山羊"))
# 能够组合& 和| 操做符以及使用括号进行分组来编写任意复杂的Q 对象。同时,Q 对象可使用~ 操做符取反,这容许组合正常的查询和取反(NOT) 查询。
# 查询做者名字是羊驼之歌而且不是2018年出版的书的书名。 models.Book.objects.filter(Q(author__name="羊驼之歌") & ~Q(publish_date__year=2018)).values_list("title")
当 and 和 or 同时一块儿用的时候 , Q 查询须要放在前面
示例
# 查询出版年份是2017或2018,书名中带羊驼的全部书。 models.Book.objects.filter(Q(publish_date__year=2018) | Q(publish_date__year=2017), title__icontains="羊驼")
此方法比一般使用稍微复杂一些。本质上和 .filter(Q(title="yang")|Q(price=123)) 实现效果相同,
可是 这样子拆分出来能够实现 不在使用字段对象,而是用字符串来筛选
场景适用:
搜索框获取当前get 请求中的参数时,参数为字符串形式,用常规的Q查询必须依靠字段对象从而没法实现
q = Q() # 将Q实例化对象单独拿出来 q.connnection = "or" # 默认多条件的关系是 "and" 经过connection 能够改为其余 q.children.append(("title", "yang")) # 添加查询字段 q.children.append(("price", 123))
限制住当前查询结束后才能够其余的操做.保证数据的可靠性
select_for_update(nowait=False, skip_locked=False)
示例
entries = Entry.objects.select_for_update().filter(author=request.user)
1 # 查询person表,判断每一个人的工资是否大于2000 2 # 利用子查询,能够写入原生的sql语句 3 ret = models.Person.objects.all().extra( 4 select={"gt": "salary > 2000"} 5 ) 6 7 # """ 8 # SELECT (salary > 2000) AS `gt`, `person`.`id`, `person`.`name`, `person`.`salary`, `person`.`dept_id` FROM `person` LIMIT 21; args=() 9 # """ 10 11 for i in ret: 12 print(i.name, i.gt)
1 # 执行彻底的原生的SQL语句,相似pymql 2 from django.db import connection 3 cursor = connection.cursor() # 获取光标,等待执行SQL语句 4 cursor.execute("""SELECT * from person where id = %s""", [1]) 5 row = cursor.fetchone() 6 print(row)