相关知识盘点:查看orm内部sql语句的方法
1.看是否是queryset 对象,是的话,可直接.query查看SQL语句;
2.在django配置文件中,配置相关参数,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',
},
}
}
案例相关:
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=255)
price = models.DecimalField(max_digits=8,decimal_places=2)
publish_date = models.DateField(auto_now_add=True)
# 库存数
kucun = models.IntegerField(null=True)
# 卖出数
maichu = models.IntegerField(null=True)
publish = models.ForeignKey(to='Publish') # 默认是跟publish的主键字段做的一对多外键关联
authors = models.ManyToManyField(to='Author')
# 虚拟字段 1.自动创建第三张表 2.帮助orm跨表查询
class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=32)
# email = models.EmailField() # 就是varchar(254)
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
author_detail = models.OneToOneField(to='AuthorDetail')
class AuthorDetail(models.Model):
phone = models.BigIntegerField()
addr = models.CharField(max_length=64)
1.查询的方法:
1.all(): 查询所有结果
2.filter(**kwargs): 它包含了与所给筛选条件相匹配的对象
3.get(**kwargs): 返回数据对象,结果只有一个,没匹配到报错
4.exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象
eg:
print(models.Book.objects.exclude(pk=1)) #只要pk不是1的数据全部查询出来
5.order_by(*field): 对查询结果排序;默认是升序,加-就是降序
eg:
print(models.Book.objects.order_by('price')) # 默认是升序
print(models.Book.objects.order_by('-price')) # 加负号就是降序
6.reverse(): 对查询结果反向排序
eg:
print(models.Book.objects.order_by('price').reverse())
注:前面要先有排序才能反向
7.count(): 返回数据库中匹配查询(QuerySet)
eg:
print(models.Book.objects.count()) #对查询出来的结果进行一个计数
8.first(): 返回第一条记录
9.last(): 返回最后一条记录
10.exists():存在返回True,否则返回False
eg:
print(models.Book.objects.filter(pk=1000).exists())
11.values(*field): 返回一个ValueQuerySet对象,运行后得到的并不是一系列
eg:
print(models.Book.objects.values('title','price')) # 得到的结果是列表套字典
12.values_list(*field): 它与values()类似
eg:
print(models.Book.objects.values_list('title','price')) # 得到的结果是列表套元组
13.distinct(): 从返回结果中剔除重复纪录
eg:
print(models.Book.objects.values('title','price','create_time').distinct())
注:去重的前提是 一定要有完全重复的数据 才能去重
2.双下滑查询:
1.__gt: 大于
eg:查询价格大于200的书籍
res = models.Book.objects.filter(price__gt=200)
2.__lt: 小于
eg:查询价格小于200的书籍
res = models.Book.objects.filter(price__lt=200)
3.__gte:大于等于
eg:查询价格大于等于200.22的书籍
res = models.Book.objects.filter(price__gte=200.22)
4.__lte:小于等于
eg:查询价格小于等于200.22的书籍
res = models.Book.objects.filter(price__lte=200.22)
5.__in:或者
eg:查询价格要么是200,要么是300,要么是666.66
res = models.Book.objects.filter(price__in=[200,300,666.66])
6.__range:区间 左右都包括
eg:查询价格在200到800之间的
res = models.Book.objects.filter(price__range=(200,800))
7.__contains:模糊匹配
eg:查询书籍名字中包含p的
res = models.Book.objects.filter(title__contains='p') # 仅仅只能拿小写p
res = models.Book.objects.filter(title__icontains='p') # 忽略大小写
8.__startswith:以...开头
eg:查询书籍是以三开头的
res = models.Book.objects.filter(title__startswith='三')
9.__endswith:以...结尾
eg:查询书籍是以三结尾的
res = models.Book.objects.filter(title__endswith='三')
10.__year:查询年相关的
eg:查询出版日期是2017的年(******)
res = models.Book.objects.filter(create_time__year='2017')
3.多表查询:
一对多的字段的增删改查:
增:
publish_id传数字:
models.Book.objects.create(title='三国演义',price=189.99,publish_id=1)
publish直接传出版社对象:
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='红楼梦',price=999.99,publish=publish_obj)
改:
传数字的:
models.Book.objects.filter(pk=1).update(publish_id=3)
传对象的:
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.filter(pk=1).update(publish=publish_obj)
删:
models.Publish.objects.filter(pk=2).delete() # 默认都是级联更新 级联删除
多对多字段的增删改查:
增(add):既可以传数字也可以传对象并且支持一次性传多个,逗号隔开即可
1.要给主键为1的书籍添加两个作者
传数字:
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.add(1)
book_obj.authors.add(2,3)
传对象:
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
author_obj2 = models.Author.objects.filter(pk=3).first()
book_obj.authors.add(author_obj)
book_obj.authors.add(author_obj1,author_obj2)
改(set):
1.将主键为1的书籍对象 作者修改为2,3
传数字:
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.set([2,])
book_obj.authors.set([2,3])
传对象:
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
author_obj2 = models.Author.objects.filter(pk=3).first()
book_obj.authors.set([author_obj,])
book_obj.authors.set([author_obj, author_obj1, author_obj2])
注:1.set中要传可迭代对象,可迭代对象中 可以是多个数字组合也可以是多个对象组合;
2.数字与对象不要混着用!!!
删(remove|clear):remove支持传数字,对象,并且可以传多个; clear不需要传任何参数
传数字:
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.remove(3)
book_obj.authors.remove(1,2)
传对象:
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
author_obj2 = models.Author.objects.filter(pk=3).first()
book_obj.authors.remove(author_obj)
book_obj.authors.remove(author_obj1,author_obj2)
什么都不传:将xx跟xx的关系全部清空
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.clear() # 清空当前书籍与作者的所有关系
注: 对象点击多对多虚拟字段 会直接跨到多对多的第三张表
4.跨表查询:
正向与反向概念:
1.一对一
正向:author---关联字段在author表里--->authordetail 按字段
反向:authordetail---关联字段在author表里--->author 按表名小写
2.一对多
正向:book---关联字段在book表里--->publish 按字段
反向:publish---关联字段在book表里--->book 按表名小写_set.all() 因为一个出版社对应着多个图书
3.多对多
正向: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)
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)
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)
小结:
当反向查询的结果有多个时,要在后面加上_set;
连表操作(基于__):
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)
2.查询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)
3.查询手机号是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)
4.查询书籍id是1 的作者的电话号码
res = models.Book.objects.filter(pk=1).values('authors__author_detail__phone')
print(res)
5.查询出版社为北方出版社的所有图书的名字和价格
res = models.Publish.objects.filter(name='北方出版社').values('book__title','book__price')
print(res)
6.查询北方出版社出版的价格大于19的书
res = models.Book.objects.filter(price__gt=19,publish__name='北方出版社').values('title','publish__name')
print(res)
注:只要表里面有外键字段,你就可以无限制跨多张表
eg:外键字段1__外键字段2...__外键字段__普通字段n
聚合查询(aggregate):最大,最小,个数,平均,总和
先导入 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'))
注: aggregate(后面可跟多个函数)
分组查询(annotate):models.那个表名就以那个分组
from django.db.models import Max, Min, Count, Avg, Sum
1.统计每一本书的作者个数
res = models.Book.objects.annotate(author_num = Count('authors')).values('author_num','title')
print(res)
2.统计出每个出版社卖的最便宜的书的价格
res = models.Publish.objects.annotate(mmp = Min('book__price')).values('name','mmp')
print(res)
3.统计不止一个作者的图书
res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1)
print(res)
4.查询各个作者出的书的总价格
res = models.Author.objects.annotate(sp=Sum('book__price')).values('name','sp')
print(res)
F查询:本质就是从数据库中获取某个字段的值
from django.db.models import F
1.查询卖出数量
res = models.Book.objects.filter(kucun__gt=F('maichu'))
print(res)
2.将书籍库存数全部增加1000
models.Book.objects.update(kucun=F('kucun')+1000)
3.把所有书名后面加上'新款'
要先导入:
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查询:默认and,可人为改为 or , not
from django.db.models import Q
1.查询书籍名称是三国演义或者价格是444.44
and:
res = models.Book.objects.filter(title='三国演义',price=444.44) # filter只支持and关系
res1 = models.Book.objects.filter(Q(title='三国演义'),Q(price=444)) # 如果用逗号 那么还是and关系
or:
res2 = models.Book.objects.filter(Q(title='三国演义')|Q(price=444))
not:
res3 = models.Book.objects.filter(~Q(title='三国演义')|Q(price=444))
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)
知识兔