查看orm内部sql语句的方法有哪些
1.如果是queryset对象 那么可以点query直接查看该queryset的内部sql语句
2.在django项目的配置文件中 配置一下参数即可实现所有的orm在查询的时候自动打印对应的sql语句
Django终端打印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',
},
}
}
把这个文件复制粘贴到Django项目的settings.py文件中,配置完了之后orm会自动打印内部SQL语句
里面有有一个LIMIT21 是orm给做了一个优化 限制条数 先一次给一部分 要了再查 减少了数据库的压力
# 查询价格大于200的书籍
res = models.Book.objects.filter(price__gt=200)
print(res)
# 查询价格小于200的书籍
res = models.Book.objects.filter(price__lt=200)
print(res)
# 查询价格大于等于200.22的书籍
res = models.Book.objects.filter(price__gte=200.22)
print(res)
# 查询价格小于等于200.22的书籍
res = models.Book.objects.filter(price__lte=200.22)
print(res)
# 查询价格要么是200,要么是300,要么是666.66
res = models.Book.objects.filter(price__in=[200,300,666.66])
print(res)
# 查询价格在200到800之间的
res = models.Book.objects.filter(price__range=(200,800)) # 两边都包含
print(res)
# 查询书籍名字中包含p的
res = models.Book.objects.filter(title__contains='p') # 仅仅只能拿小写p
res = models.Book.objects.filter(title__icontains='p') # 忽略大小写
print(res)
# 查询书籍是以三开头的
res = models.Book.objects.filter(title__startswith='三')
res1 = models.Book.objects.filter(title__endswith='p')
print(res)
print(res1)
# 查询出版日期是2017的年
res = models.Book.objects.filter(create_time__year='2017')
print(res)
多表操作
图书馆里系统表创建
一对多:ForeignKey
一对一:OneToOneField,可以用ForeignKey代替ForeignKey(unique=True)
一对多和一对一两个关键字所创建出来的字段会自动加上_id后缀
多对多:ManyToManyFiled,这个字段不会真正的在表当中显示出来,它只是一个虚拟字段
1.告诉orm自动创建第三种表
2.帮助orm跨表查询
一对多字段的增删改查
增
改
删
models.Publish.objects.filter(pk=2).delete() #默认都是级联更新,级联删除
多对多字段的增删改查
增
改
将主键为1的书籍对象作者修改为2,3
删
跨表查询
正向与反向的概念
一对一
正向:author---关联字段在author表里--->authordetail 按字段
反向:authordetail---关联字段在author表里--->author 按表名小写
一对多
正向:book---关联字段在book表里--->publish 按字段
反向:publish---关联字段在book表里--->book 按表名小写_set.all() 因为一个出版社对应着多个图书
多对多
正向:book---关联字段在book表里--->author 按字段
反向:author---关联字段在book表里--->book 按表名小写_set.all() 因为一个作者对应着多个图书
正向查询按外键字段
反向查询按表名小写
基于对象的跨表查询(子查询: 将一张表的查询结果当做另外一个查询语句的条件)
# 1.查询书籍id是1 的出版社名称
book_obj = models.Book.objects.filter(pk=1).first()
print(book_obj.publish.name)
print(book_obj.publish.addr)
# 2.查询书籍id是2 的作者姓名
book_obj = models.Book.objects.filter(pk=2).first()
print(book_obj.authors) # app01.Author.None
print(book_obj.authors.all())
res = book_obj.authors.all()
for r in res:
print(r.name)
# 3.查询作者是jason的家庭住址
author_obj = models.Author.objects.filter(name='jason').first()
print(author_obj.author_detail.addr)
# 4.查询出版社是东方出版社出版的书籍
publish_obj = models.Publish.objects.filter(name='东方出版社').first()
# print(publish_obj.book_set) # app01.Book.None
print(publish_obj.book_set.all())
# 5.查询作者是jason的写过的所有的书籍
author_obj = models.Author.objects.filter(name='jason').first()
print(author_obj.book_set) # app01.Book.None
print(author_obj.book_set.all())
# 6.查询电话号码是130的作者姓名
author_detail_obj = models.AuthorDetail.objects.filter(phone=130).first()
print(author_detail_obj.author.name)
print(author_detail_obj.author.age)
"""
当反向查询的结果是多个的时候,那么就需要加_set,否则的话直接表明小写就可以了
"""
# 7.查询书籍id为1 的作者的电话号码
book_obj = models.Book.objects.filter(pk=1).first()
author_list = book_obj.authors.all()
for author_obj in author_list:
print(author_obj.author_detail.phone)
双下划线的跨表查询(连表操作)left join,inner join,right join,union
# 正向
# 1.查询jason作者的手机号
res = models.Author.objects.filter(name='jason').values('author_detail__phone','author_detail__addr')
print(res)
res1 = models.AuthorDetail.objects.filter(author__name='jason').values('phone')
print(res1)
# 查询jason这个作者的年龄和手机号
# 正向
res = models.Author.objects.filter(name='jason').values('age','author_detail__phone')
print(res)
# 反向
res1 = models.AuthorDetail.objects.filter(author__name='jason').values('phone','author__age')
print(res1)
# 查询手机号是130的作者年龄
# 正向
res = models.AuthorDetail.objects.filter(phone=130).values('author__age')
print(res)
# 反向
res1 = models.Author.objects.filter(author_detail__phone=130).values('age')
print(res1)
# 查询书籍id是1 的作者的电话号码
res = models.Book.objects.filter(pk=1).values('authors__author_detail__phone')
res1 = models.Book.objects.filter(pk=1).values('外键字段1__外键字段2__外键字段3__普通字段')
print(res)
"""只要表里面有外键字段 你就可以无限制跨多张表"""
# 1.查询出版社为北方出版社的所有图书的名字和价格
res = models.Publish.objects.filter(name='北方出版社').values('book__title','book__price')
print(res)
# 2.查询北方出版社出版的价格大于19的书
res = models.Book.objects.filter(price__gt=19,publish__name='北方出版社').values('title','publish__name')
print(res)
聚合查询
# 1.统计所有书的总价格
from django.db.models import Max,Min,Count,Avg,Sum
# res = models.Book.objects.aggregate(Sum('price'))
res1 = models.Book.objects.aggregate(Avg('price'))
res2 = models.Book.objects.aggregate(Count('price'))
res3 = models.Book.objects.aggregate(Max('price'))
res4 = models.Book.objects.aggregate(Min('price'))
res5 = models.Book.objects.aggregate(Max('price'),Min('price'),Count('pk'),Avg('price'),Sum('price'))
print(res5)
print(res)
print(res1)
print(res2)
分组查询
# 统计每一本书的作者个数
from django.db.models import Max, Min, Count, Avg, Sum
res = models.Book.objects.annotate(author_num = Count('authors')).values('author_num','title')
print(res)
# 统计出每个出版社卖的最便宜的书的价格
res = models.Publish.objects.annotate(mmp = Min('book__price')).values('name','mmp')
print(res)
# 统计不止一个作者的图书
res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1)
print(res)
"""只要是queryset对象,就可以无限制的调用queryset对象的方法,最最用的就是对一个已经filter过滤完的数据 再进行更细化的筛选"""
# 查询各个作者出的书的总价格
res = models.Author.objects.annotate(sp=Sum('book__price')).values('name','sp')
print(res)
F查询
F查询的本质就是从数据库中获取某个字段的值
# 查询库存数大于卖出数的书籍
"""之前查询等号后面的条件都是我们自己输入的,现在变成了需要从数据库中获取数据放在等号后面"""
from django.db.models import F
res = models.Book.objects.filter(kucun__gt=F('maichu'))
print(res)
# 将书籍库存数全部增加1000
models.Book.objects.update(kucun=F('kucun')+1000)
# 把所有书名后面加上'新款'
from django.db.models.functions import Concat
from django.db.models import Value
ret3 = models.Book.objects.update(title=Concat(F('title'), Value('新款')))
models.Book.objects.update(title = F('title')+'新款') # 不能这么写
Q查询
from django.db.models import Q
# 查询书籍名称是三国演义或者价格是444.44
res = models.Book.objects.filter(title='三国演义',price=444.44) # filter只支持and关系
res1 = models.Book.objects.filter(Q(title='三国演义'),Q(price=444)) # 如果用逗号,那么还是and关系
res2 = models.Book.objects.filter(Q(title='三国演义')|Q(price=444))
res3 = models.Book.objects.filter(~Q(title='三国演义')|Q(price=444))
print(res2)
# Q高级用法
q = Q()
q.connector = 'or' # 修改查询条件的关系,默认是and
q.children.append(('title__contains', '三国演义')) # 往列表中添加筛选条件
q.children.append(('price__gt', 444)) # 往列表中添加筛选条件
res = models.Book.objects.filter(q) # filter支持直接传q对象,但是默认还是and关系
print(res)