Django基础五之django模型层(二)多表操作 (3)

反向查询时,如果定义了related_name ,则用related_name替换 表名,例如:

publish = ForeignKey(Book, related_name='bookList') # 练习: 查询人民出版社出版过的所有书籍的名字与价格(一对多) # 反向查询 不再按表名:book,而是related_name:bookList obj=models.Publish.objects.filter(name="清华出版社").values("bookList__title","bookList__price") 聚合函数 from django.db.models import Avg,Min,Max ,Sum,Count # 计算所有书籍的平均价格 图书价格的最大值 #aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定一个名称,可以向聚合子句提供它。 obj=models.Book.objects.all().aggregate(a=Avg('price'),m=Max('price')) print(obj) #{'a': 47.5, 'm': Decimal('78.00')} print(obj['m']-2) #76.00 分组查询 # 统计每个出版社出版的书籍的平均价格 ret=models.Book.objects.values('publish_id').annotate(a=Avg('price')) print(ret) #<QuerySet [{'publish_id': 2, 'a': 69.0}, {'publish_id': 3, 'a': 30.0}, {'publish_id': 4, 'a': 22.0}]> ret=models.Publish.objects.annotate(a=Avg('book__price')) print(ret) #<QuerySet [<Publish: 山西出版社>, <Publish: 清华出版社>, <Publish: 江苏出版社>]> ret = models.Publish.objects.annotate(a=Avg('book__price')).values('name', 'a') print(ret) #<QuerySet [{'name': '山西出版社', 'a': 22.0}, {'name': '清华出版社', 'a': 69.0}, {'name': '江苏出版社', 'a': 30.0}]> F查询

在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?我们在book表里面加上两个字段:评论数:comment,收藏数:good

#查询点赞数大于评论数的书籍 ret=models.Book.objects.filter(good__gt=F('comment')) # 查询点赞数大于评论数+20的书籍 #Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。 ret=models.Book.objects.filter(good__gt=F('comment')+20) print(ret) #<QuerySet [<Book: 今天是个好日子>, <Book: java核心>]> #所有书籍的价格+20 models.Book.objects.all().update(price=F('price')+20) #评论数大于100,和 ,点赞数大于100的 ret=models.Book.objects.filter(good__gt=100,comment__gt=100) print(ret) #<QuerySet [<Book: java核心>, <Book: 故事会新编>]> Q查询

Q 对象可以使用&(与) 、|(或)、~(非) 操作符组合起来。当一个操作符在两个Q 对象上使用时,它产生一个新的Q 对象。

你可以组合& 和| 操作符以及使用括号进行分组来编写任意复杂的Q 对象。同时,Q 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询:

#评论数大于100,或者 点赞数大于100的 ret=models.Book.objects.filter(Q(good__gt=100)|Q(comment__gt=100)) print(ret) #<QuerySet [<Book: java核心>, <Book: 故事会新编>, <Book: LINUX学习>]> #评论数大于100,或者 点赞数小于等于100的 ret = models.Book.objects.filter(~Q(good__gt=100) | Q(comment__gt=100)) print(ret) #评论数大于100,或者 点赞数大于100的 且 price='42' #逗号连接的普通查询条件放在最后 #查询函数可以混合使用Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面。例如: ret = models.Book.objects.filter(Q(good__gt=100) | Q(comment__gt=100),price='42') print(ret) #评论数大于100,或者 点赞数大于100的 且 price='42' ret = models.Book.objects.filter(Q(good__gt=100) | Q(comment__gt=100) & Q(price='42')) #&优先级高 ret = models.Book.objects.filter(Q(Q(good__gt=100) | Q(comment__gt=100)) & Q(price='42')) #|优先级高 orm执行原生sql语句

在模型查询API不够用的情况下,我们还可以使用原始的SQL语句进行查询。

  Django 提供两种方法使用原始SQL进行查询:一种是使用raw()方法,进行原始SQL查询并返回模型实例;另一种是完全避开模型层,直接执行自定义的SQL语句。

  执行原生查询

    raw()管理器方法用于原始的SQL查询,并返回模型的实例:

    注意:raw()语法查询必须包含主键

    这个方法执行原始的SQL查询,并返回一个django.db.models.query.RawQuerySet 实例。 这个RawQuerySet 实例可以像一般的QuerySet那样,通过迭代来提供对象实例。

ret=models.Publish.objects.raw('select * from app01_publish;') print(ret) #<RawQuerySet: select * from app01_publish;> for i in ret: print(i.name) # 直接执行自定义SQL # django提供的接口中获取数据库连接,然后像使用pymysql模块一样操作数据库 from django.db import connection, connections cursor = connection.cursor() # cursor = connections['default'].cursor() cursor.execute("""SELECT * from auth_user where id = %s""", [1]) ret = cursor.fetchone() 查看orm生成原生sql语句 ret=models.Publish.objects.all() print(ret) from django.db.models import connection print(connection.queries) 综合查询练习题 #1 查询每个作者的姓名以及出版的书的最高价格 ret=models.Author.objects.values('name').annotate(max_price=Max('book__price')) print(ret) #注意:values写在annotate前面是作为分组依据用的,并且返回给你的值就是这个values里面的字段(name)和分组统计的结果字段数据(max_price) #ret=models.Author.objects.annotate(max_price=Max('book__price')).values('name','max_price')#这种写法是按照Author表的id字段进行分组,返回给你的是这个表的所有model对象,这个对象里面包含着max_price这个属性,后面写values方法是获取的这些对象的属性的值,当然,可以加双下划线来连表获取其他关联表的数据,但是获取的其他关联表数据是你的这些model对象对应的数据,而关联获取的数据可能不是你想要的最大值对应的那些数据 # 2 查询作者id大于2作者的姓名以及出版的书的最高价格 ret=models.Author.objects.filter(id__gt=2).annotate(max_price=Max('book__price')).values('name','max_price')#记着,这个values取得是前面调用这个方法的表的所有字段值以及max_pirce的值,这也是为什么我们取关联数据的时候要加双划线的原因 print(ret) #3 查询作者id大于2或者作者年龄大于等于20岁的女作者的姓名以及出版的书的最高价格 ret=models.Author.objects.filter(Q(id__gt=2)|Q(age__gte=20),sex='female').annotate(max_price=Max('book__price')).values('name','max_price') #4 查询每个作者出版的书的最高价格 的平均值 ret=models.Author.objects.values('id').annotate(max_price=Max('book__price')).aggregate(Avg('max_price')) #{'max_price__avg': 555.0} 注意,aggregate是queryset的终止句,得到的是字典 ret=models.Author.objects.annotate(max_price=Max('book__price')).aggregate(Avg('max_price')) #{'max_price__avg': 555.0} 注意,aggregate是queryset的终止句,得到的是字典 补充 url.py 中的url(r'^admin/', admin.site.urls)路由操作admin.py

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyzygx.html