ORM多表更新删除 查询
删除和修改
一对一和一对多的操作
# 修改和删除操作 def edit_book(request): # 一对一修改 # 方式一: 通过模型类对象 au_det_obj = models.AuthorDetail.objects.get(id=3) models.Author.objects.filter(id=1).update(name="bob",ad=au_det_obj) # # 方式二 models.Author.objects.filter(id=5).update(name="jack",ad_id=1) # 一对多修改:同一对一 # 方式一: pub_obj = models.Publish.objects.get(id=2) models.Book.objects.filter(id=6).update(pud=pub_obj) # 方式二: models.Book.objects.filter(id=7).update(pud_id=3) # 删除: 注意级联删除关系, 相关的数据都会删掉 models.Author.objects.get(id=1).delete() models.Author.objects.filter(id=3).delete() models.AuthorDetail.objects.filter(id=4).delete() return HttpResponse('OK')
多对多关系的删除和更新
# 多对多的删除和更新 # 删除remove book_obj = models.Book.objects.get(id=1) book_obj.authors.remove(8) # 删除一条 book_obj = models.Book.objects.get(id=6) book_obj.authors.remove(7, 8) # 删除多条 # 清空clear book_obj = models.Book.objects.get(id=4) book_obj.authors.clear() # 更新 book_obj = models.Book.objects.get(id=3) book_obj.authors.set("7") # 参数是可迭代类型数据 # 更改多条 book_obj.authors.set([7,8,9]) # set动作有两步:1 先执行clear 2 再执行add添加
多表查询
基于对象的跨表查询(子查询)
正向查询: 关系属性写在哪个表里面,那么通过这个表的数据,去查询关联的另外一张表的数据,就叫做正向查询,反之就是反向查询
# 一对一正向查询 # 查陈六六作者的电话号码 author_obj = models.Author.objects.get(name="陈六六") # author_obj.ad 找到了author_obj关联的作者详细信息表里面对应记录 print(author_obj.ad.telephore) # 777 # 反向查询 : 反向查询用关联它的模型类的名称小写 # 查询地址为北京的作者名称 aut_det_obj = models.AuthorDetail.objects.get(address="四川") print(aut_det_obj.author.name) # 陈七七 # 一对多正向查询 同一对一查询 # 查询人生是哪个出版社的 book_obj = models.Book.objects.get(title="人生") print(book_obj.pud.name) # 小树出版社 # 反向查询 模型类名小写_set # 查询小树出版社出版哪些书 pub_obj = models.Publish.objects.get(name="小树出版社") print(pub_obj.book_set.all()) # <QuerySet [<Book: Book object>, <Book: Book object>]> 类似于objects控制器 print(pub_obj.book_set.all().values("title")) # <QuerySet [{'title': '人生'}, {'title': '人类'}]> # 多对多查询 # 正向查询 使用属性来查 # 查询人生是谁写的 book_obj = models.Book.objects.get(title="人生") print(book_obj.authors.all().values("name")) # <QuerySet [{'name': '陈六六'}, {'name': '陈七七'}, {'name': '张三'}]> # 反向查询 使用模型类名小写_set # 查询陈六六写了哪些书 author_obj = models.Author.objects.get(name="陈六六") print(author_obj.book_set.all().values("title")) # <QuerySet [{'title': '人间'}, {'title': '人生'}]> return HttpResponse('OK')
查看原生SQL语句的方法
1 ORM语句.query
2 在settings配置文件中写上如下内容,就能够自动打印出我们执行orm语句对应的sql语句 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } } 3 通过django配置的连接mysql的管道来查看(pymysql) from app01 import models def add_book(request): ''' 添加表记录 :param request: http请求信息 :return: ''' book_obj = models.Book(title='python',price=123,pub_date='2012-12-12',publish='人民出版社') book_obj.save() from django.db import connection #通过这种方式也能查看执行的sql语句 print(connection.queries) return HttpResponse('ok')
# 一对一正向查询 使用属性 # 查询陈七七作者的地址 res = models.Author.objects.filter(name="陈七七").values("ad__address") print(res) # <QuerySet [{'ad__address': '四川'}]> # 反向查询 表名小写 res = models.AuthorDetail.objects.filter(author__name="陈七七").values("address") print(res) # <QuerySet [{'address': '四川'}]> # 一对多正向查询 # 查询人世是哪个出版社的 res = models.Book.objects.filter(title="人世").values("pud__name") print(res) # <QuerySet [{'pud__name': '小草出版社'}]> # 反向操作 res = models.Publish.objects.filter(book__title="人世").values("name") print(res) # <QuerySet [{'name': '小草出版社'}]> # 多对多正向查询 使用关联属性 # 查询人类这本书是谁写的 res = models.Book.objects.filter(title="人类").values("authors__name") print(res) # <QuerySet [{'authors__name': 'jack'}]> # 反向查询 res = models.Author.objects.filter(book__title="人类").values("name") print(res) # <QuerySet [{'name': 'jack'}]>
# 聚合查询 from django.db.models import Max, Min, Avg, Count, Sum # 统计一下所有书籍的平均价格 res = models.Book.objects.aggregate(Avg("price")) print(res) # {'price__avg': 62.757143} 结果是普通字典类型 # 可以起别名 res = models.Book.objects.aggregate(a=Avg("price"),b=Max("price")) print(res) # {'a': 62.757143, 'b': Decimal('99.90')} # aggregate方法可以看为是orm语句的结束语句,结果为普通字典类型,不能在继续调用queryset或者模型类对象提供的方法了
# 分组查询 必须制定别名 # 查询一下每个出版社出版书的平均价格 from django.db.models import Max, Min, Avg, Count, Sum res = models.Book.objects.values("pud_id").annotate(a=Avg("price")) print(res) # <QuerySet [{'pud_id': 1, 'a': 99.9}, {'pud_id': 2, 'a': 39.9}, {'pud_id': 3, 'a': 59.9}]> res = models.Book.objects.values("pud_id","id").annotate(a=Avg("price")) print(res) # values里面可以加多个分组条件 # 以出版社名称分组的书的平均价格 res = models.Book.objects.values("pud__name").annotate(a=Avg("price")) print(res) # <QuerySet [{'pud__name': '小草出版社', 'a': 39.9}, {'pud__name': '小树出版社', 'a': 59.9}, {'pud__name': '小花出版社', 'a': 99.9}]> res = models.Publish.objects.annotate(a=Avg("book__price")) print(res) # <QuerySet [<Publish: Publish object>, <Publish: Publish object>, <Publish: Publish object>]> # 返回结果是Publish的模型类对象,这个模型类对象里面包含Publish的所有属性数据,还有annotate的统计结果数据 ret = res.values("name","a") print(ret) # <QuerySet [{'name': '小草出版社', 'a': 39.9}, {'name': '小树出版社', 'a': 59.9}, {'name': '小花出版社', 'a': 99.9}]>
# F查询 # F查询可以用来做本表不同字段之间的一个比较 # 查询点赞数大于评论数的书籍 from django.db.models import F res = models.Book.objects.filter(dianzan__gt=F("comment")) print(res) # <QuerySet [<Book: 人间>, <Book: 人生>, <Book: 人类>]> # F可以用来对本表数据进行一些统一操作(四则运算都支持) # 将所有的书籍上调10块钱 models.Book.objects.all().update(price=F("price")+10)
# Q查询 filter中的查询条件默认是and关系 # 可以进行多条件查询,查询关系可以是 或与非 from django.db.models import Q # ~ 条件取反 ,&--and关系 ,|--or关系 # 查询书名中包含以小开头的,或者评论数在350以上的 res = models.Book.objects.filter(Q(title__startswith="小")|Q(comment__gt=350)) print(res) # <QuerySet [<Book: 小猫>, <Book: 猫生>, <Book: 小狗>]> # 查询书名中包含小的,或者评论数在350以上的,并且点赞数大于400的 res = models.Book.objects.filter(Q(title__startswith="小")|Q(comment__gt=350),dianzan__gt=400) print(res) # <QuerySet [<Book: 猫生>, <Book: 小狗>]> # 注意,如果结合逗号来进行and的关系查询,那么必须将没有Q包裹的查询条件放在Q包裹的查询条件后面 #下面这种方式也可以,Q查询可以多层嵌套使用 res = models.Book.objects.filter(Q(title__startswith="小") | Q(comment__gt=350)&Q( dianzan__gt=400)) print(res) # <QuerySet [<Book: 小猫>, <Book: 猫生>, <Book: 小狗>]>