Day 09 基于ORM记录查询

阅读: 评论:0

Day 09 基于ORM记录查询

Day 09 基于ORM记录查询

Day 09 基于ORM记录查询

写在前面的话

  • 模板语言:每个语言的web框架都会有模板语言,django—》dtl
  • 模板语言的渲染,是再后端完成的
  • 用php写前端(html,css,js)(不对的)
  • 前后端分离:前后端交互,统一全用json格式
  • 前端只专注于写前端(vue,react:前端工程化),后端只专注于写后端(提供接口,交互json格式数据)

一、聚合查询

1.1 聚合函数的导入

from dels import Avg,Sum, Min, Max, Sum, Count

1.2 聚合函数的使用

# 1 计算所有图书的平均价格
# aggregate结束,已经不是queryset对象了
book = Book.objects.all().aggregate(Avg('price'))
print(book, type(book))  # 得到是 字段名__聚合函数小写:内容的 字典
# 起别名
book = Book.objects.all().aggregate(avg=Avg('price'))
print(book)
---------------------------------------------------------
{'price__avg': 46.8796} <class 'dict'>
{'avg': 46.8796}
# 2 计算总图书数
book_count_dic = Book.objects.all().aggregate(count=Count('id'))
print(book_count_dic)
----------------------------------------------------------
{'count': 50}
# 3 计算最低价格的图书
book_price_min = Book.objects.all().aggregate(min=Min('price'))
print(book_price_min)
----------------------------------------------------------
{'min': Decimal('1.30')}
 # 4 计算所有书的价格
book_price_sum = Book.objects.all().aggregate(sum=Sum('price'))
print(book_price_sum)
-----------------------------------------------------------
{'sum': Decimal('2343.98')}

二、分组查询

重点:annotate() 内写聚合函数

  • values在表示group by的字段
  • values在表示取某几个字段
  • filter在表示where
  • filter在表示having
    # 1、查询出版社id大于15的出版社id,以及出书平均价格# select publish_id,avg(price) from app01_book where publish_id>1 group by publish_id;price_avg = Book.objects.values('publish__id').filter(publish__id__gt=15).annotate(avg=Avg('price')).values('publish__name', 'price', 'name', 'avg')li = []for i in price_avg:if i['name'] not in li:li.append(i['name'])# print(i['publish__name'], i['price'], i['avg'])print(len(li))--------------------------16

与数据库查看的数据相同

    # 2# 统计每一个出版社的最便宜的书author_min_price = Book.objects.values('publish__id').annotate(min=Min('price')).values('publish__name', 'min')for i in author_min_price:print(i['publish__name'], i['min'])# 3# 统计每一本以py开头的书籍的作者个数:startswith_hu = Book.objects.values('publish__id').filter(name__startswith='湖').annotate(count=Count('publish__id')).values('publish__name', 'count')for i in startswith_hu:print(i['publish__name'], i['count'])# 4# 作者数量大于2的图书名字和价格author_gtt = Publish.objects.values('book__id').annotate(count=Count('book__id')).filter(count__gte=2).values('book__name','book__price', 'count')for i in author_gtt:print(i['book__name'], i['book__price'], i['count'])

三、F和Q查询

F查询:

F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。

from dels import F, Q# 修改id为25 书籍的价格 + 100book35 = Book.objects.filter(id=25).update(price=F('price')+100)# 查询id数大于价格的书籍books = Book.objects.filter(id__gt=F('price')).values( 'name','id','price')for i in books:print(i)

注意:F和Q只适用于 Quire_SET对象,也就是说get,first,last 是不适用的

Q查询:制造 与或非的条件

filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR语句),你可以使用Q对象

与(|)
    # 查询 作者id为8 并且 出版社id为3 的书籍名称和出版社名字res = Book.objects.filter(Q(author__id=8) & Q(publish__id=3)).values('name', 'publish__name')print(res)
-------------------------------
<QuerySet [{'name': '西藏自治区的老奶奶', 'publish__name': '尼日利亚出版社'}]>
或(&)
    # 查询作者id 为4 或者8的 作者,书籍的名称,和出版社名字res = Book.objects.filter(Q(author__id=4) | Q(author__id=8)).values('author__name', 'name', 'publish__name')for i in res:print(i)
---------------------------------
{'author__name': '王婷', 'name': '甘肃省不相信眼泪', 'publish__name': '尼泊尔出版社'}
{'author__name': '王婷', 'name': '甘肃省不相信眼泪', 'publish__name': '沙特阿拉伯出版社'}
{'author__name': '马晶', 'name': '西藏自治区的老奶奶', 'publish__name': '尼日利亚出版社'}
{'author__name': '马晶', 'name': '西藏自治区的老奶奶', 'publish__name': '多米尼加共和国出版社'}
非(~)
    res = Publish.objects.filter(~Q(book__name='湖南省不相信眼泪') & Q(book__publish__id=2)).values('book__name', 'id','book__id')for i in res:print(i)

四、原生SQL语句

方案一:用的比较少

    from django.db import connectioncursor = connection.cursor()ute("""SELECT * from app01_book where id = %s""", [1])# row = cursor.fetchone()row = cursor.fetchall()print(row)

本质与 pymysql 执行方法没啥不同

  • 先创建连接
  • 创造游标
  • 游标接口执行SQL语句
  • 返回结构 fetchall 或者 fethone

方案二:用的多

# 查询id大于 45 的所有书籍信息
books = Book.objects.raw('select * from app01_book where id >45')
for i in books:print(i.id, i.name, i.price)# 跨表查询res = Book.objects.raw('select app01_book.id, app01_book.name as name2,app01_author.name from app01_book inner join app01_author on app01_book.author_id=app01_author.id')for i in res:print(i.name2, i.id, i.name)

五、defer和only

    # defer和only(查询优化相关)# only保持是book对象,但是只能使用only指定的字段# books = models.Book.objects.all().only('name')# print(books[0].name)# print(books[0].price)  # 能出来,但是会再执行一句SQL语句# books = models.Book.objects.all().only('name')## print(books[0].__dict__)books = models.Book.objects.all().defer('name','price')print(books[0].__dict__)

六、事务(请求,装饰器,局部)

事务的特性ACID

  1. 原⼦性: 事务是最⼩的执⾏单位,不允许分割。事务的原⼦性确保动作要么全部完成,要么完全不起作⽤;
  2. ⼀致性: 执⾏事务前后,数据保持⼀致,多个事务对同⼀个数据读取的结果是相同的;
  3. 隔离性: 并发访问数据库时,⼀个⽤户的事务不被其他事务所⼲扰,各并发事务之间数据库是独⽴的;
  4. 持久性: ⼀个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发⽣故障也不应该对其有任何 影响。

事务的三个粒度

1、局部使用
    from django.db import transactionwith transaction.atomic(): # 都在事物中,要么都成功,要么都失败author_detail=models.ate(addr='xxx',phone='123',sex=1)# raise Exception('抛了异常')author=models.ate(name='llqz',age=19,author_detail=author_detail)
2、视图函数装饰器,这一个视图函数都在一个事物中
@transaction.atomicdef index(request):return HttpResponse('ok')
3、整个http请求,在事物中,在setting.py中配置
DATABASES = {'default': {...'PORT': 3306,'ATOMIC_REQUEST': True,}}'ATOMIC_REQUEST': True,
设置为True统一个http请求对应的所有sql都放在一个事务中执行(要么所有都成功,要么所有都失败)。

本文发布于:2024-02-01 22:10:51,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170679665039746.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:Day   ORM
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23