一。配置settings。
如果是queryset对象 那么可以点query直接查看该queryset的内部sql语句
将以下代码放入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', }, } }
二。双下划线查询。
在orm过滤查询中,有基于双下划线的查询,可以节省时间。
1.大于:__gt
可以匹配大于这个数值的数:
res = models.Book.objects.filter(price__gt=89)
2.小于__lt
匹配小于这个数值的数据:
res = models.Book.objects.filter(price__lt=89)
3.大于等于__gte
匹配大于等于这个数值的数:
res = models.Book.objects.filter(price__gte=89)
4.小于等于__lte
匹配小于等于这个数值的数:
res = models.Book.objects.filter(price__lte=89)
5。__in
匹配在后面这个数列中的所有值的数据/。
res = models.Book.objects.filter(price__in=[89,123,454])
6.__range(x,y)
匹配在这个范围中的所有数据。包括头和尾。
res = models.Book.objects.filter(price__range=[55,123])
7.__contains
模糊匹配,字段中包函这个字段的数据。
res = models.Book.objects.filter(title__contains='p')
这个匹配区分大小写。下面这个方法不区分。
8.__icontains
res = models.Book.objects.filter(title__icontains='P')
9.__startswith
匹配开头时这个数值的数据
res = models.Book.objects.filter(title__startswith='计')
10.__endswith
匹配结尾这个数值的数据
res = models.Book.objects.filter(title__endswith='互')
11.__year
匹配时间数据类型中年份为该年的数据:
res = models.Book.objects.filter(publish_date__year=2019)
res = models.Book.objects.filter(publish_date__month=9)
当然,其中还有其他过滤日期的方法。
(自己理解):
对于像onetoonefield,foreign,manytomany等字段,都是 有母子之分的。
也就是说这个虚拟字段在哪个表里,哪个表就是子表。
而我们把根据子表查询母表时的动作叫正向查询。
正向查询都是按找字段名查找。
根据母表数据查询子表数据的动作叫反向查询。
反向查询都是按照表名小写_set查找。
得到的结果就是那个表的对象。
而在1对1 的时候不需要加_set,只需要小写就行。
三。关于外键的增删改。
1.一对多
增:
可以按照id值传入外键:
models.Book.objects.create(title='三国演义',price=189.99,publish_id=1)
也可以将那个对象传入:
publish_obj = models.Publish.objects.filter(pk=2).first() models.Book.objects.create(title='红楼梦',price=999.99,publish=publish_obj)
改:
将id数字传入:
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()
2,多对多字段的增删改。
增:
增加操作多借助于add(),是一个正对query对象的方法。
#要给主键为1的书籍添加两个作者 book_obj = models.Book.objects.filter(pk=1).first() print(book_obj.authors) # 对象点击多对多虚拟字段 会直接跨到多对多的第三张表 book_obj.authors.add(1) book_obj.authors.add(2,3)
add()也支持传入对象,添加对象:
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()
set支持传入数据:
将主键为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])
但是set中要是一个可迭代对象。但不能混合使用。
删:
删除操作使用的是remove函数:
可以支持数字:
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)
除了remove之外,还可以使用clear,将这个对象的所有联系都清空。
book_obj = models.Book.objects.filter(pk=1).first() book_obj.authors.clear() # 清空当前书籍与作者的所有关系
这些操作也支持_set反向操作。
四。基于对象的跨表查询。
多表查询的方法可以先将一个条件对象找到,通过他下面的虚拟字段或者起子表_set的方法获取表对象,在提取想要的信息。
例子:
查询作者是jason的家庭住址 author_obj = models.Author.objects.filter(name='jason').first() print(author_obj.author_detail.addr) 查询出版社是东方出版社出版的书籍 publish_obj = models.Publish.objects.filter(name='东方出版社').first() # print(publish_obj.book_set) # app01.Book.None print(publish_obj.book_set.all()) 查询作者是jason的写过的所有的书籍 author_obj = models.Author.objects.filter(name='jason').first() print(author_obj.book_set) # app01.Book.None print(author_obj.book_set.all())
注意,在获取了表之后,可以继续对其使用对表对象使用的一切方法。
五。基于双下划线的跨表查询。
双下划线作用于任何关于表的字段的获取,其可以获取另一个它关联的表的字段数据。
双下划线不分子母表。
values()函数相当于原生sql语句中的select后面的值。其返回的也是一个queryset对象。其中传入的是字段
例子:
查询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')
例子2:
# 查询手机号是130的作者年龄 # 正向 res = models.AuthorDetail.objects.filter(phone=130).values('author__age') print(res) # 反向 res1 = models.Author.objects.filter(author_detail__phone=130).values('age')
只要表里有外键字段,就可以无限跨多张表:
res1 = models.Book.objects.filter(pk=1).values('外键字段1__外键字段2__外键字段3__普通字段')
六。聚合查询:
聚合查询和sql原生语句差不都:
1.Sum()求和
2.Avg()求平均值
3.Count()计数
4.Max()最大值
5.Min()最小值
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()
这个函数中可以使用聚合函数,使用聚合函数产生的结果可以给他起别名,再通过value展示。
res = models.Publish.objects.annotate
(mmp = Min('book__price')).values('name','mmp')
如果annotate之前不使用value进行指定字段,就将这个表的id作为分组对象。指定了value就将value中的字段进行分组。
例子:
查询各个作者出的书的总价格 res = models.Author.objects.annotate(
sp=Sum('book__price')).values('name','sp')
八。f查询与q查询。
f。将数据库中的数据取出转化成可操作的。
当你需要查询一个值的数据两端都是数据库中的值时。可以使用f将后面那个值包起来,这样系统会根据记录一条条比对:
from django.db.models import F res = models.Book.objects.filter(kucun__gt=F('maichu')) # 将书籍库存数全部增加1000 models.Book.objects.update(kucun=F('kucun')+1000)
这个操作可以将数据库中本来的数据拿出来使用f操作进行转换,转换成课进行操作的对象:
# 把所有书名后面加上'新款' 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')+'新款') # 不能这么写
其中concat就是拼接字符串操作(再数据库中),而value就是将字符串转化成可操作的数据。
q。将数据库的数据取出,转化成可进行逻辑比较的。
如果需要将两个字段的数据一起匹配时可以使用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))
# 非操作。
在q前面加上~表示非操作。
衍生:
当需要使用字符串作为表字段名进行操作的时候,可以使用q。
也就是说不会提前知道字段名,只知道该字段是个字符串。
# 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)
补充:
1.在一对一字段中OnoToOneField操作可以用ForeignKey代替(ForeignKey(unique=True))
2.虚拟字段除了关联第三张表之外,还能帮助orm跨表查询。