/ORM操做13条基础-单表查询-外键-多对多-聚合和分组查询-F-Q-事物html
day74 1. 内容回顾 1. ORM 1. 13条 1. 返回queryset的 all() filter() exclude() order_by() reverse() distinct() values() values_list() 2. 返回对象的 get() first() last() 3. 返回布尔值 exists() 4. 返回数字 count() 2. django使用mysql数据库的步骤 1. 建立一个mysql数据库 2. 配置 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'orm_homework', 'USER': 'root', 'PASSWORD': '', 'HOST': '127.0.0.1', 'PORT': 3306, } } 3. 告诉django使用pymysql链接你的mysql数据库(mysqldb) 在与settings同级目录下的__init__.py中写 import pymysql pymysql.install_as_MySQLdb() 4. 在APP下的models.py中写类(继承Model) 5. 执行数据库迁移的命令 python manage.py makemigrations # 记录models的变动记录 python manage.py migrate # 将变动记录同步到数据库中 2. 周末做业 见代码 3. OneToOneField(to='关联的表') (一对一) 在ForeignKey基础上加一个约束 unique=true 1. 全部的内容能够写在一个表中 2. 有的字段不常查,但有的字段查的很频繁 4. 外键ForeignKey book_obj.publisher ——》 关联的出版社对象 book_obj.publisher_id 反向查询: 不指定related_name pub_obj.book_set ——》关系管理对象 指定related_name='books' pub_obj.books ——》关系管理对象 5. 多对多ManyToManyField book_obj.author 多对多的方法: create() add() remove() set() clear() 6. 单表的增删改查 create delete update() .属性 = '' save() 7. 进阶 1. 聚合和分组 aggregate 终止子句 annotate 2. F 和 Q ~取反 & and | 或 3. 事务 2. 今日内容 0. 登陆的实例 1. cookie 1. cookie是什么? cookie是保存在浏览器上一组组键值对 2. 特性: 1. 是服务器让浏览器设置的。浏览器有权利不设置。 2. 访问其余页面的时候携带着cookie。 2. 能干什么? 1. 作登陆 2. session 1. 保存在服务器上的键值对 2. 一个cookie对应一个session 流程: 1. 给首次登陆的用户设置一个cookie session:asdasdasasdasdas 2. 开辟一块空间存session 3. session中存要存的数据(键值对) 4. 返回给浏览器cookie # 设置session request.session['is_login'] = 'True' # 获取session request.session.get('is_login', '')
https://www.cnblogs.com/maple-shaw/articles/9403501.htmlpython
https://www.cnblogs.com/maple-shaw/articles/9323320.htmlmysql
https://www.cnblogs.com/maple-shaw/articles/9414626.html -练习题git
# 查找全部书名里包含金老板的书 # ret=models.Book.objects.filter(title__icontains='金老板').values_list('title') # print(ret) # 查找出版日期是2018年的书 # ret=models.Book.objects.filter(publisher_date__year=2018).values_list('title','publisher_date') # print(ret) # 查找出版日期是2017年的书名 # ret=models.Book.objects.filter(publisher_date__year=2017).values_list('title','publisher_date') # print(ret) # 查找价格大于10元的书 # ret=models.Book.objects.filter(price__gt=10).values_list('title') # print(ret) # 查找价格大于10元的书名和价格 # ret = models.Book.objects.filter(price__gt=10).values_list('title', 'price') # print(ret) # 查找memo字段是空的书 # ret=models.Book.objects.filter(memo__isnull=True) # print(ret) # 查找在北京的出版社 # ret=models.Publisher.objects.filter(city__icontains='北京').values_list('name','city') # print(ret) # 查找名字以沙河开头的出版社 # ret = models.Publisher.objects.filter(name__startswith='沙河').values_list('name', 'city') # print(ret) ############----------------重点-------------------------#################### # 查找“沙河出版社”出版的全部书籍 # ret=models.Book.objects.filter(publisher__name='沙河出版社').values_list('publisher__name','title') # print(ret) # 查找每一个出版社出版价格最高的书籍价格 # ret=models.Publisher.objects.annotate(max=Max('books__price')).values_list('name','books__title','max') # print(ret) # ret=models.Book.objects.filter(publisher__name='沙河出版社') # print(ret) # ret=models.Publisher.objects.filter(books__title='跟金老板学开车') # print(ret) # 查找每一个出版社的名字以及出的书籍数量 # ret=models.Publisher.objects.annotate(num=Count('books')).values_list('name','num') # print(ret) # 查找做者名字里面带“小”字的做者 # ret=models.Author.objects.filter(name__contains='小').values_list('name') # print(ret) # ret=models.Author.objects.all().values_list('name') # print(ret) # 查找年龄大于30岁的做者 # ret=models.Author.objects.filter(age__gt=30).values_list('name','age','authors__title') # print(ret) # 查找手机号是155开头的做者 # ret=models.Author.objects.filter(phone__startswith=155).values_list('name','phone') # print(ret) # ret=models.Author.objects.all().values_list('phone') # print(ret) # 查找手机号是155开头的做者的姓名和年龄 # ret=models.Author.objects.filter(phone__startswith=155).values_list('name','age') # print(ret) # 查找每一个做者写的价格最高的书籍价格 # ret=models.Author.objects.annotate(max=Max('authors__price')).values_list('name','authors__price') # print(ret) # 查找每一个做者的姓名以及出的书籍数量 # ret=models.Author.objects.all().annotate(num=Count('authors')).values_list('name','num') # print(ret) # 查找书名是“跟金老板学开车”的书的出版社 # book_obj=models.Book.objects.filter(title='跟金老板学开车') # ret=book_obj.publisher # print(ret) # 查找书名是“跟金老板学开车”的书的出版社所在的城市 # book_obj=models.Book.objects.get(title='跟金老板学开车') # ret=book_obj.publisher.city # print(ret) # 查找书名是“跟金老板学开车”的书的出版社的名称 # book_obj=models.Book.objects.filter(title='跟金老板学开车') # ret=book_obj.publisher.name # print(ret) # 查找书名是“跟金老板学开车”的书的出版社出版的其余书籍的名字和价格 # book_obj=models.Book.objects.get(title='跟金老板学开车') # ret=book_obj.publisher.books.exclude(title='跟金老板学开车').values_list('title','price') # print(ret) # ret=models.Publisher.objects.get(books__title='跟金老板学开车').books.exclude(title='跟金老板学开车').values_list('title','price') # print(ret) # obj=models.Publisher.objects.get(book__title='跟金老板学开车').book_set.exclude(title='跟金老板学开车').values_list('title','price') # ret=obj.book_set.all() # print(obj) # 查找书名是“跟金老板学开车”的书的全部做者 # ret=models.Book.objects.get(title='跟金老板学开车').author.all() # print(ret) # 查找书名是“跟金老板学开车”的书的做者的年龄 # ret=models.Book.objects.get(title='跟金老板学开车').author.all().values_list('age','name') # print(ret) # 查找书名是“跟金老板学开车”的书的做者的手机号码 # ret=models.Book.objects.get(title='跟金老板学开车').author.all().values_list('phone','name') # print(ret) # 查找书名是“跟金老板学开车”的书的做者们的姓名以及出版的全部书籍名称和价钱 # book_obj = models.Book.objects.get(title='跟金老板学开车') # ret=book_obj.author.all() # for aut in ret: # print(aut) # ret=aut.authors.all().values_list('title','price') # print(ret) # ret=models.Author.objects.filter(authors__title='跟金老板学开车').values('name','authors__title','authors__price') # print(ret)
/ sql
/数据库
/django
/浏览器
QuerySet
API referencehttps://docs.djangoproject.com/en/1.11/ref/models/querysets/服务器
/cookie
/
/
/
import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
#上面的代码,在manage.py文件里也有,能够考虑复制过来
#引入django import django django.setup()
#引入models
from app01 import models books = models.Book.objects.all() print(books)
1,在项目下建一个文件夹,而后建一个py文件,把上面代码粘贴进去,
2,写好语句后, 右键执行便可,不用在启动django项目,直接看结果,
示例代码:
import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings") import django django.setup() from app01 import models ret = models.Person.objects.all() print(ret[0],'**',type(ret),'**',type(ret[0]))
输出结果
ret=models.Person.objects.all() #类型是类,QuerySet对象 type(ret)---><class 'django.db.models.query.QuerySet'> ret[0] Person object type(ret[0]) <class 'app01.models.Person'>
/
/
order_by的默认排序, ordering=('id','age'),ID同样,再按age进行排序,
class Person(models.Model): id=models.AutoField(primary_key=True) name=models.CharField(max_length=32) age=models.IntegerField() birth=models.DateField() def __str__(self): return "<Person obj:{} {}>".format(self.id,self.name) # 加上这个以后,默认取出来就是已经排序的 class Meta: #后面要写元组, ordering=('id')
下面再写的取出来就是倒序了
ret=models.Person.objects.all().reverse()
也能够这样写,
models.Person.objects.all().order_by('id').reverse()
具体演示代码
import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings") import django django.setup() from app01 import models # all 获取全部对象 ——》 QuerySet ret = models.Person.objects.all() # get 获取单独的对象 ——》 对象 # 找不到或者找到多个就报错 ret= models.Person.objects.get(id=1,name='阿旭') # filter 过滤 获取全部知足条件的对象 ——》QuerySet ret = models.Person.objects.filter(id=1) # exclude 获取不知足条件的全部对象 ret = models.Person.objects.exclude(id=1) # values ——》QuerySet 元素是字典 # 不写参数 默认全部字段的名字和值 # 写参数 拿到指定字段的名字和值 ret = models.Person.objects.all().values('id','name') ret = models.Person.objects.values('id','name') # values_list ——》QuerySet 元素是元组 只有值没有字段名 # 不写参数 默认全部字段值 # 写参数 拿到指定字段值 ret = models.Person.objects.values_list('name','id') # print(ret) # for i in ret : # print(i,type(i)) # reverse 对已经排序的QuerySet进行反转 ret = models.Person.objects.all().reverse() # distinct 去重 ——》QuerySet # count 对QuerySet中的元素进行计数 ret = models.Person.objects.filter(id=100).count() # first 取QuerySet中的第一个元素 ret = models.Person.objects.all().first() # last 取QuerySet中的最后一个元素 ret = models.Person.objects.all().last() ret = models.Person.objects.values_list().last() ret = models.Person.objects.filter(id=100).first() # exists 判断查询结果是否有值 ret = models.Person.objects.filter(id=100).exists() # print(ret) # order_by 按字段进行排序 ——》QuerySet ret =models.Person.objects.order_by('age') print(ret)
/
/
all(),
filter(),
exclude(),
order_by(), 里面能够放多个参数
reverse(),对已经排序的进行翻转
distinct(),去重
values() 返回一个可迭代的字典序列,里面能够放参数,放了参数就是仅显示参数的内容,
values_list() 返回一个可迭代的元祖序列, 也能够放参数,
get(), 取不到或者取到多个会报错
first(), 取不到是Null
last().
exists()
count()
id__lt,id__gt,id__in,id__range=[]是列表
name__contains='str'
name__icontains='str'
name__startswith='xx'
name__endswith='xx'
name__iendswith='xx'
birth__year
eq 就是 EQUAL等于
ne 就是 NOT EQUAL不等于
gt 就是 GREATER THAN大于
lt 就是 LESS THAN小于
gte 就是 GREATER THAN OR EQUAL 大于等于
lte 就是 LESS THAN OR EQUAL 小于等于
import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings") import django django.setup() from app01 import models ret = models.Person.objects.all() #小于10的,less than ret=models.Person.objects.filter(id__lt=10) #大于1的,great than ret=models.Person.objects.filter(id__gt=3) #大于等于3的, ret=models.Person.objects.filter(id__gt=3) #大于3小于5的, ret=models.Person.objects.filter(id__gt=3,id__lt=5) #取反,拿出小于等于3的, ret=models.Person.objects.exclude(id__gt=3) #还能够设置范围,还能够换成exclude ret=models.Person.objects.filter(id__in=[1,3,5]) #使用range,1和5都能取到, ret=models.Person.objects.filter(id__range=[1,5]) #查选包含特定字符的, ret=models.Person.objects.filter(name__contains='啊') #注意加了一个i,是不区分大小写的意思, ret=models.Person.objects.filter(name__icontains='啊') #表示以哪一个字符为开头 ret=models.Person.objects.filter(name__startswith='阿') #以什么结尾, ret=models.Person.objects.filter(name__endswith='阿') #加了一个i,不区分大小写, ret=models.Person.objects.filter(name__iendswith='阿') #查找日期符合条件的, ret=models.Person.objects.filter(birth__year='2018') ret=models.Person.objects.filter(birth__month='09') ret=models.Person.objects.filter(birth__year='2018',birth__month='09') print(ret)
Django终端打印SQL语句
在Django项目的settings.py文件中在最后复制粘贴以下代码:
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }
即为你的Django项目配置上一个名为django.db.backends的logger实例便可查看翻译后的SQL语句。
/
/
外键设置在书籍,经过book查询publisher,称之为正向查询,反过来就是反向查询,
#book_obj.publishr是直接拿到了publisher对象了,关联的出版社对象, print(book_obj.publisher,type(book_obj.publisher)) 输出:Publisher object <class 'app01.models.Publisher'>
#区分两者的sql语句条数
print(book_obj.publisher_id)
print(book_obj.publisher.id)
语法:
对象.关联字段.字段
book_obj = models.Book.objects.first() # 第一本书对象 print(book_obj.publisher) # 获得这本书关联的出版社对象 print(book_obj.publisher.name) # 获得出版社对象的名称
models.Book.objects.filter(publisher__name='新华出版社') #查出 出版社='新华出版社' 出版的全部书,
此处就是publisher查找book
/
语法:
拿到关联对象
publisher_obj = models.Publisher.objects.first() # 找到第一个出版社对象
books = publisher_obj.book_set.all() # 找到第一个出版社出版的全部书
titles = books.values_list("title") # 找到第一个出版社出版的全部书的书名
示例代码1
import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings") import django django.setup() from app01 import models # 正向查询 book ——》 publisher # 基于对象查询 # book_obj = models.Book.objects.get(id=1) # print(book_obj.id) # print(book_obj.title) # print(book_obj.publisher_id) # print(book_obj.publisher_id) # 关联的出版社对象 # print(book_obj.publisher.id) # 关联的出版社对象 # print(book_obj.publisher.name) # 基于字段查询 # ret= models.Book.objects.filter(publisher__name='沙河出版社') # ret= models.Book.objects.filter(publisher_id=1) # print(ret) # 反向查询 publisher ——》 book # 基于对象的查询 # 一 —— 》 多 表名小写_set ——》 管理对象 .all() 出版社关联的全部书籍对象 pub_obj = models.Publisher.objects.first() # 表名小写_set # print(pub_obj) # ret = pub_obj.book_set.all() # print(pub_obj.book_set,type(pub_obj.book_set)) # print(ret) # 指定了related_name books # print(pub_obj.books.all()) # 基于字段的查询 ret = models.Publisher.objects.filter(xx__title='跟太亮学开车') print(ret)
关于查找时,能够简化的写法,
在models里面须要对应设置,注意related_name的添加, 也是反向查询用的,
class Book(models.Model): title=models.CharField(max_length=32) #下面一行是要关联的外键 publisher=models.ForeignKey('Publisher',related_name='books',on_delete=models.CASCADE)
ret=models.Publisher.objects.filter(books__title='这就是书名') #此处的books__title books是related_name
#若是下面图片的related_query_name='xx',写了,上面的books__title就要换成:xx__title,
与图片的关系
pub_obj=models.Publisher.objects.first() pub_obj.books.create(title='跟老男孩学思想')
/
/
"关联管理器"是在一对多或者多对多的关联上下文中使用的管理器。
它存在于下面两种状况:
简单来讲就是当 点后面的对象 可能存在多个的时候就可使用如下的方法。
拿到管理对象,
author_obj=models.Author.objects.get(id=1) # books就是设置的那个多对多,books=models.ManyToManyField('Book') print(author_obj.books,type(author_obj.books)) #拿到管理对象, # 输出:app01.Book.None <class 'django.db.models.fields.related_descriptors print(author_obj.books.all()) #拿到QuerySet #输出:<QuerySet [<Book: <Person obj:5 跟太亮学开车>>, <Book: <Person obj:6 跟太白学烫头>>]>
#create # 1,建立书籍对象(与出版社进行关联) # 2,该对象和做者 author_obj = models.Author.objects.get(id=1)
此处的books就是以前的->books=models.ManyToManyField('Book')
author_obj.books.create(title='XX与嫂子的故事',publisher_id=1)
/
/
/
add()括号里面能够放一个或多个数据, 能够放id,还能够放对象,
#给做者添加书籍, author_obj = models.Author.objects.get(id=1) #能够添加一个或多个,add() # author_obj.books.add(9) author_obj.books.add(5,6,8,9)
区分与set的不一样
author_obj.books.set([1,6,8,9])
另外一种添加方式
author_obj=models.Author.objects.get(id=1) # 获取指定id的书籍 books=models.Book.objects.filter(id__in=[1,6,8,9]) #须要打散才能进行传参 author_obj.books.add(*books)
与add对比使用,add是添加的一个id,或者一个对象,
set能够添加列表,或者queryset集合,
author_obj=models.Author.objects.get(id=1) books=models.Book.objects.filter(id__in=[1,6,8,9]) # 下面两行的代码是等价的, # author_obj.books.set([1,6,8,9]) author_obj.books.set(books)
/
/
author_obj=models.Author.objects.get(id=1) books=models.Book.objects.filter(id__in=[1,6,8,9]) # remove 能够移除一个或多个 author_obj.books.remove(1) author_obj.books.remove(6,8,9) # 能够移除对象 author_obj.books.remove(*books)
clear()
从关联对象集中移除一切对象。
author_obj=models.Author.objects.get(id=1) #把跟这个做者关联的书,都清空掉, author_obj.books.clear()
设置null=True
就是删除出版社跟书的对应关系时,外键没有了,往数据库写的时候,写不进去,须要设置null=True才能写进去,
在models里设置Book类,而后执行两条命令.
注意:
设置null=True
publisher=models.ForeignKey('Publisher',related_name='books',on_delete=models.CASCADE,null=True)
设置null=True以后,示例代码
pub_obj=models.Publisher.objects.get(id=1) #一对多的管理对象remove不能使用id,使用对象 # pub_obj.books.remove(models.Book.objects.get(id=5)) #清空这个出版社下全部关联的书, pub_obj.books.clear()
/
/
models里面,Book类添加包含小数的字段
price=models.DecimalField(max_digits=5,decimal_places=2)
1,aggregate的使用,观察输出结果,
ret=models.Book.objects.all().aggregate(Avg('price')) print(ret,type(ret)) # 输出:{'price__avg': 50.0} <class 'dict'>
还能够更名字
ret=models.Book.objects.all().aggregate(make_name=Avg('price'))
print(ret,type(ret))
# {'make_name': 50.0} <class 'dict'>
还能够多放参数
ret=models.Book.objects.all().aggregate(Avg('price'),Max('price'))
2,能够更名字,还能够多放参数,
/
/
1,统计每本书的做者个数
# 统计每本书的做者个数 #.all能够省略不写, # ret=models.Book.objects.all().annotate(Count('author')) ret=models.Book.objects.annotate(Count('author')) for i in ret.values(): print(i)
输出结果
'''输出: {'id': 1, 'title': '宫保鸡丁指南', 'publisher_id': 1, 'price': Decimal('10.00'), 'author__count': 1} {'id': 2, 'title': '包子真贵', 'publisher_id': 4, 'price': Decimal('20.00'), 'author__count': 1} {'id': 3, 'title': '陶馨园真便宜', 'publisher_id': 5, 'price': Decimal('30.00'), 'author__count': 1} {'id': 4, 'title': '护国寺豆汁真骚', 'publisher_id': 3, 'price': Decimal('40.00'), 'author__count': 0} {'id': 5, 'title': '跟太亮学开车', 'publisher_id': 1, 'price': Decimal('50.00'), 'author__count': 1} {'id': 6, 'title': '跟太白学烫头', 'publisher_id': 1, 'price': Decimal('60.00'), 'author__count': 1} {'id': 7, 'title': '新华字典', 'publisher_id': 2, 'price': Decimal('70.00'), 'author__count': 1} {'id': 8, 'title': '戴绿与嫂子的故事', 'publisher_id': 1, 'price': Decimal('80.00'), 'author__count': 0} {'id': 9, 'title': '跟老男孩学思想', 'publisher_id': 1, 'price': Decimal('90.00'), 'author__count': 0} '''
2,统计每一个出版社最便宜的书,
ret=models.Publisher.objects.annotate(Min('books__price')).values() for i in ret.values(): print(i)
3,统计不止一个做者的图书,
#统计不止一个做者的图书, ret=models.Book.objects.annotate(count=Count('author')).filter(count__gt=1) print(ret)
4,查询做者出的书的总价格
# 查询做者出的书的总价格 ret=models.Author.objects.annotate(sum=Sum('books__price')).values() print(ret)
先进行导入
from django.db.models import F
示例代码
# F查询 from django.db.models import F # ret=models.Book.objects.filter(sale__gt=50).values() #F查询,直接查出sale大于kucun的, ret=models.Book.objects.filter(sale__gt=F('kucun')).values() #还能够加减数值 ret=models.Book.objects.filter(sale__gt=F('kucun')+30).values() print(ret)
对数据的修改:update与save的区别,save的效率要慢,
#对数据的修改, models.Book.objects.all().update(sale=100) #区分update与save的差异, book_obj=models.Book.objects.get(id=1) book_obj.sale=0 book_obj.save()
filter() 等方法中的关键字参数查询都是一块儿进行“AND” 的。
若是你须要执行更复杂的查询(例如OR语句),你可使用Q对象。
先进行导入
from django.db.models import Q
ret=models.Book.objects.filter(Q(id__lt=3)|Q(id__gt=5)) # print(ret) for i in ret: print(i) ret = models.Book.objects.filter(Q(id__gt=3)&Q(id__lt=9)) # print(ret) for i in ret: print(i)
还能够进行取反
ret=models.Book.objects.filter(~Q(id__lt=3)|Q(id__gt=5)) # print(ret) for i in ret: print(i)
/
import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings") import django django.setup() import datetime from app01 import models try: from django.db import transaction with transaction.atomic(): new_publisher = models.Publisher.objects.create(name="火星出版社") models.Book.objects.create(title="橘子物语", publish_date=datetime.date.today(), publisher_id=10) # 指定一个不存在的出版社id except Exception as e: print(str(e))
# extra # 在QuerySet的基础上继续执行子语句 # extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None) # select和select_params是一组,where和params是一组,tables用来设置from哪一个表 # Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,)) # Entry.objects.extra(where=['headline=%s'], params=['Lennon']) # Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"]) # Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid']) 举个例子: models.UserInfo.objects.extra( select={'newid':'select count(1) from app01_usertype where id>%s'}, select_params=[1,], where = ['age>%s'], params=[18,], order_by=['-age'], tables=['app01_usertype'] ) """ select app01_userinfo.id, (select count(1) from app01_usertype where id>1) as newid from app01_userinfo,app01_usertype where app01_userinfo.age > 18 order by app01_userinfo.age desc """ # 执行原生SQL # 更高灵活度的方式执行原生SQL语句 # from django.db import connection, connections # cursor = connection.cursor() # cursor = connections['default'].cursor() # cursor.execute("""SELECT * from auth_user where id = %s""", [1]) # row = cursor.fetchone() ORM 执行原生SQL的方法
################################################################## # PUBLIC METHODS THAT ALTER ATTRIBUTES AND RETURN A NEW QUERYSET # ################################################################## def all(self) # 获取全部的数据对象 def filter(self, *args, **kwargs) # 条件查询 # 条件能够是:参数,字典,Q def exclude(self, *args, **kwargs) # 条件查询 # 条件能够是:参数,字典,Q def select_related(self, *fields) 性能相关:表之间进行join连表操做,一次性获取关联的数据。 总结: 1. select_related主要针一对一和多对一关系进行优化。 2. select_related使用SQL的JOIN语句进行优化,经过减小SQL查询的次数来进行优化、提升性能。 def prefetch_related(self, *lookups) 性能相关:多表连表操做时速度会慢,使用其执行屡次SQL查询在Python代码中实现连表操做。 总结: 1. 对于多对多字段(ManyToManyField)和一对多字段,可使用prefetch_related()来进行优化。 2. prefetch_related()的优化方式是分别查询每一个表,而后用Python处理他们之间的关系。 def annotate(self, *args, **kwargs) # 用于实现聚合group by查询 from django.db.models import Count, Avg, Max, Min, Sum v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id')) # SELECT u_id, COUNT(ui) AS `uid` FROM UserInfo GROUP BY u_id v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id')).filter(uid__gt=1) # SELECT u_id, COUNT(ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1 v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id',distinct=True)).filter(uid__gt=1) # SELECT u_id, COUNT( DISTINCT ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1 def distinct(self, *field_names) # 用于distinct去重 models.UserInfo.objects.values('nid').distinct() # select distinct nid from userinfo 注:只有在PostgreSQL中才能使用distinct进行去重 def order_by(self, *field_names) # 用于排序 models.UserInfo.objects.all().order_by('-id','age') def extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None) # 构造额外的查询条件或者映射,如:子查询 Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,)) Entry.objects.extra(where=['headline=%s'], params=['Lennon']) Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"]) Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid']) def reverse(self): # 倒序 models.UserInfo.objects.all().order_by('-nid').reverse() # 注:若是存在order_by,reverse则是倒序,若是多个排序则一一倒序 def defer(self, *fields): models.UserInfo.objects.defer('username','id') 或 models.UserInfo.objects.filter(...).defer('username','id') #映射中排除某列数据 def only(self, *fields): #仅取某个表中的数据 models.UserInfo.objects.only('username','id') 或 models.UserInfo.objects.filter(...).only('username','id') def using(self, alias): 指定使用的数据库,参数为别名(setting中的设置) ################################################## # PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS # ################################################## def raw(self, raw_query, params=None, translations=None, using=None): # 执行原生SQL models.UserInfo.objects.raw('select * from userinfo') # 若是SQL是其余表时,必须将名字设置为当前UserInfo对象的主键列名 models.UserInfo.objects.raw('select id as nid from 其余表') # 为原生SQL设置参数 models.UserInfo.objects.raw('select id as nid from userinfo where nid>%s', params=[12,]) # 将获取的到列名转换为指定列名 name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'} Person.objects.raw('SELECT * FROM some_other_table', translations=name_map) # 指定数据库 models.UserInfo.objects.raw('select * from userinfo', using="default") ################### 原生SQL ################### from django.db import connection, connections cursor = connection.cursor() # cursor = connections['default'].cursor() cursor.execute("""SELECT * from auth_user where id = %s""", [1]) row = cursor.fetchone() # fetchall()/fetchmany(..) def values(self, *fields): # 获取每行数据为字典格式 def values_list(self, *fields, **kwargs): # 获取每行数据为元祖 def dates(self, field_name, kind, order='ASC'): # 根据时间进行某一部分进行去重查找并截取指定内容 # kind只能是:"year"(年), "month"(年-月), "day"(年-月-日) # order只能是:"ASC" "DESC" # 并获取转换后的时间 - year : 年-01-01 - month: 年-月-01 - day : 年-月-日 models.DatePlus.objects.dates('ctime','day','DESC') def datetimes(self, field_name, kind, order='ASC', tzinfo=None): # 根据时间进行某一部分进行去重查找并截取指定内容,将时间转换为指定时区时间 # kind只能是 "year", "month", "day", "hour", "minute", "second" # order只能是:"ASC" "DESC" # tzinfo时区对象 models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.UTC) models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.timezone('Asia/Shanghai')) """ pip3 install pytz import pytz pytz.all_timezones pytz.timezone(‘Asia/Shanghai’) """ def none(self): # 空QuerySet对象 #################################### # METHODS THAT DO DATABASE QUERIES # #################################### def aggregate(self, *args, **kwargs): # 聚合函数,获取字典类型聚合结果 from django.db.models import Count, Avg, Max, Min, Sum result = models.UserInfo.objects.aggregate(k=Count('u_id', distinct=True), n=Count('nid')) ===> {'k': 3, 'n': 4} def count(self): # 获取个数 def get(self, *args, **kwargs): # 获取单个对象 def create(self, **kwargs): # 建立对象 def bulk_create(self, objs, batch_size=None): # 批量插入 # batch_size表示一次插入的个数 objs = [ models.DDD(name='r11'), models.DDD(name='r22') ] models.DDD.objects.bulk_create(objs, 10) def get_or_create(self, defaults=None, **kwargs): # 若是存在,则获取,不然,建立 # defaults 指定建立时,其余字段的值 obj, created = models.UserInfo.objects.get_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 2}) def update_or_create(self, defaults=None, **kwargs): # 若是存在,则更新,不然,建立 # defaults 指定建立时或更新时的其余字段 obj, created = models.UserInfo.objects.update_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 1}) def first(self): # 获取第一个 def last(self): # 获取最后一个 def in_bulk(self, id_list=None): # 根据主键ID进行查找 id_list = [11,21,31] models.DDD.objects.in_bulk(id_list) def delete(self): # 删除 def update(self, **kwargs): # 更新 def exists(self): # 是否有结果 QuerySet方法大全
#统计不止一个做者的图书,
ret=models.Book.objects.annotate(count=Count('author')).filter(count__gt=1)
print(ret)