【单表操作】
用mysql数据库的时候,别忘在__init__里写这两行代码
import pymysql
pymysql.install_as_MySQLdb()
(测试脚本代码环境)
1 单独测试django某个功能层 2 默认不允许单独测试某个py文件,必须先建路由对应关系,然后在视图函数里面才能执行ORM语句 3 如果想要测试某个单独的ORM语句怎么办? 4 -------------------------------- 5 测试环境1:pycharm提供的python console 6 但有个不好,代码写完没法保存!! 7 ---------- 8 测试环境2:自己搭建(自带的test或者自己创建) 9 1.拷贝manage.py前四行 10 2.自己再加两行 11 import django 12 django.setup()
。
。
(单表操作的增删改查)
1 模型表: 2 3 class User(models.Model): 4 name = models.CharField(max_length=32) 5 age = models.IntegerField() 6 # register_time= models.DateTimeFiel d(auto_now_add=True) 7 register_time = models.DateField() # 年月日 8 # register_time=models.DateTimeField(auto_now_add=True) 9 ''' 10 DateField:年月日 11 DateTimeField:时分秒 12 有两个非常重要的参数 13 auto_now:每次操作数据的时候,该字段会自动将当前时间更新 14 auto_now_add:在创建数据的时候,会自动将当前创建时间记录下来,之后只要不人为的修改,那么就不会发生改变 15 ''' 16 17 # # 辨别last()方法 18 def __str__(self): 19 return '对象:%s' % self.name 20 21 --------------- 22 测试脚本py文件 23 24 import os 25 26 if __name__ == '__main__': 27 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoProject5day0064.settings') 28 import django 29 30 django.setup() 31 from app01 import models 32 33 # 增--方式一 34 models.User.objects.create(name='jason', age=18, register_time='2022-12-12') 35 # 日期格式 36 import datetime 37 38 # 方式二: 39 ctime = datetime.datetime.now() 40 user_obj = models.User(name='egon', age=20, register_time=ctime) 41 user_obj.save() 42 43 44 # 删 45 res = models.User.objects.filter(name='egon').delete() 46 # 删--根据pk删 47 res = models.User.objects.filter(pk=2).delete() 48 print(res) # 所删除影响的行数 (1, {'app01.User': 1}) 49 ''' 50 pk:会自动查找到当前表的主键字段,指代的就是当前表的主键字段 51 用了pk之后,就不需要知道当前表的主键字段叫什么 52 ''' 53 # 删数据的第二种方式 54 user_obj = models.User.objects.filter(pk=1).first() 55 user_obj.delete() 56 57 58 # 修改方式一 59 models.User.objects.filter(pk=5).update(name='jason老师') 60 # 修改方式二 61 user_obj = models.User.objects.get(pk=6) 62 print(user_obj) # get方法返回的直接说当前数据对象,但是如果数据不存在,则会直接报错,不会返回None 63 user_obj.name = 'egon老师' 64 user_obj.save()
(必知必会13条)
1 # 1.create() 创建数据并直接获取当前创建的数据对象 2 # res = models.User.objects.create(name='阿兵', age=28) 3 # res = models.User.objects.create(name='oscar', age=18) 4 # res = models.User.objects.create(name='jerry', age=38) 5 # res = models.User.objects.create(name='jack', age=88) 6 # print(res) 7 ------------------------------------ 8 # 2.filter() 根据条件筛选数据 结果是QuerySet [数据对象1,数据对象2] 9 # res = models.User.objects.filter() 10 # res = models.User.objects.filter(name='jason') 11 # res = models.User.objects.filter(name='jason', age=19) 12 # 括号内支持多个条件但是默认是and关系 13 ------------------------------------ 14 # 3.first() last() QuerySet支持索引取值但是只支持正数 并且orm不建议你使用索引 15 # res = models.User.objects.filter()[1] 16 # res = models.User.objects.filter(pk=100)[0] # 数据不存在索引取值会报错 17 # res = models.User.objects.filter(pk=100).first() # 数据不存在不会报错而是返回None 18 # res = models.User.objects.filter().last() # 数据不存在不会报错而是返回None 19 ------------------------------------ 20 # 4.update() 更新数据(批量更新) 21 # models.User.objects.filter().update() 批量更新 22 # models.User.objects.filter(id=1).update() 单个更新 23 ------------------------------------ 24 # 5.delete() 删除数据(批量删除) 25 # models.User.objects.filter().delete() 批量删除 26 # models.User.objects.filter(id=1).delete() 单个删除 27 ------------------------------------ 28 # 6.all() 查询所有数据 结果是QuerySet [数据对象1,数据对象2] 29 # res = models.User.objects.all() 30 ------------------------------------ 31 # 7.values() 根据指定字段获取数据 结果是QuerySet [{},{},{},{}],列表套字典 32 # res = models.User.objects.all().values('name') 33 # res = models.User.objects.filter().values() 34 # res = models.User.objects.values() 35 ------------------------------------ 36 # 8.values_list() 根据指定字段获取数据 结果是QuerySet [(),(),(),()] 列表套元组 37 # res = models.User.objects.all().values_list('name','age') 38 ------------------------------------ 39 # 9.distinct() 去重 数据一定要一模一样才可以 如果有主键肯定不行 40 # res = models.User.objects.values('name','age').distinct() 41 ------------------------------------ 42 # 10.order_by() 根据指定条件排序 默认是升序 字段前面加负号就是降序 43 # res = models.User.objects.all().order_by('age') 44 # print(res) 45 ------------------------------------ 46 11.get() 根据条件筛选数据并直接获取到数据对象!! 47 一旦条件不存在会直接报错 不建议使用!!! 48 res = models.User.objects.get(pk=1) 49 print(res) # 直接获取到数据对象 50 res = models.User.objects.get(pk=100, name='jason') 51 print(res) # 报错!! 52 ------------------------------------ 53 12.exclude() 54 # 它包含了与所给筛选条件不匹配的对象,相当于filter的取反操作 55 res = models.User.objects.exclude(pk=1) 56 print(res) # pk不等于1的所有对象 57 ------------------------------------ 58 # 13.reverse() 颠倒顺序(被操作的对象必须是已经排过序的才可以) 59 # res = models.User.objects.all() 60 # res = models.User.objects.all().order_by('age') 61 # res1 = models.User.objects.all().order_by('age').reverse() 62 # print(res, res1) 63 ------------------------------------ 64 14.count() # 统计QuerySet结果集中的对象数量!!! 65 res = models.User.objects.all().count() 66 print(res) 67 ------------------------------------ 68 15.exists() 69 # 判断结果集中是否含有数据 如果有则返回True 没有则返回False 70 res = models.User.objects.all().exists() 71 print(res) 72 res1 = models.User.objects.filter(pk=100).exists() 73 print(res1)
【查看内部sql语句的方式】
。
。
。
【双下划线查询】
1 ''' 2 只要还是queryset对象,就可以无限制的点queryset对象的方法!!! 3 queryset.filter().values().filter().values_list().filter()... 4 ''' 5 6 7 # 要求:查询年龄大于19岁的数据 8 res = models.User.objects.filter(age__gt=19) 9 print(res) 10 # 年龄小于25的数据 11 rqs = models.User.objects.filter(age__lt=25) 12 print(rqs) 13 # 大于等于 小于等于 14 rws = models.User.objects.filter(age__gte=25) 15 print(rws) 16 rrs = models.User.objects.filter(age__lte=25) 17 print(rrs) 18 # 年龄是18 或者20 或者 27的数据 19 rts = models.User.objects.filter(age__in=[18, 20, 27]) 20 print(rts) 21 # 年龄在18到20之间的,首尾都能包括 22 rys = models.User.objects.filter(age__range=(18, 20)) 23 print(rys) 24 # 查出名字里含有n的数据,模糊查询,默认区分大小写 25 rus = models.User.objects.filter(name__contains='n') 26 print(rus) 27 # 忽略大小写 28 ris = models.User.objects.filter(name__icontains='n') 29 print(ris) 30 # 名字以什么开头,以什么结尾 31 rps = models.User.objects.filter(name__startswith='n') 32 ros = models.User.objects.filter(name__endswith='n') 33 # 注册时间是2月份的数据,按照月份 34 ras = models.User.objects.filter(register_time__month=2) 35 print(ras) 36 # 按照年月日 37 rss = models.User.objects.filter(register_time__year=2022, register_time__month=12, register_time__day=12)
。
。
。
【多表操作】
1 # 图书表 2 class Book(models.Model): 3 title = models.CharField(max_length=32) 4 price = models.DecimalField(max_digits=5, decimal_places=2) 5 publish_date = models.DateField(auto_now_add=True) 6 # 外键,一对多 7 publish = models.ForeignKey('Publish', on_delete=models.CASCADE) 8 # 多对多 9 authors = models.ManyToManyField(to='Author') 10 # F查询,增加两个字段 11 kucun = models.IntegerField(default=100) 12 maichu = models.IntegerField(default=99) 13 14 # 自定义字段的使用 15 my_field = MyCharField(max_length=32, null=True) 16 17 def __str__(self): 18 return '对象:%s' % self.title 19 20 21 # 出版社表 22 class Publish(models.Model): 23 name = models.CharField(max_length=32) 24 addr = models.CharField(max_length=32) 25 email = models.EmailField() # varchar,该字段是给校验性组件看的,不是给model看的 26 27 def __str__(self): 28 return '对象:%s' % self.name 29 30 31 # 作者表 32 33 class Author(models.Model): 34 name = models.CharField(max_length=32) 35 age = models.IntegerField() 36 # 一对一 37 author_detail = models.OneToOneField('AuthorDetail', on_delete=models.CASCADE) 38 39 40 # 作者详情表 41 class AuthorDetail(models.Model): 42 phone = models.BigIntegerField() 43 addr = models.CharField(max_length=32)
(多表的增删改查)
1 # 一对多外键的增删改查 2 3 # 增---方式一:创建一本书.直接写实际字段 4 models.Book.objects.create(title='三国演义', price=123.23, publish_id=1) 5 # 2.增---方式二: 虚拟字段,对象 6 publish_obj = models.Publish.objects.filter(pk=2).first() # 先查出有哪些对象 7 models.Book.objects.create(title='红楼梦', price=100.23, publish=publish_obj) 8 9 # 删:级联更新级联删除 10 models.Publish.objects.filter(pk=2).delete() 11 12 # 修改--方式一 13 models.Book.objects.filter(pk=1).update(publish_id=2) 14 # 修改--方式二 15 publish_obj = models.Publish.objects.filter(pk=1).first() 16 models.Book.objects.filter(pk=1).update(publish=publish_obj) 17 18 ---------------------------------------------------- 19 # 多对多的增删改查 20 21 # 如何给书籍添加作者? 22 # 前提是这第三张关联的表不是我们创建的,没办法通过点属性进行操作 23 book_obj = models.Book.objects.filter(pk=1).first() 24 print(book_obj.authors) # .authors 获取的是一个对象列表,相当于已经到了第三张关系表了 25 book_obj.authors.add(1, 2) # 书籍id为1的书籍绑定一个主键为1和2的作者 26 # 第二种关联方法 27 author_obj = models.Author.objects.filter(pk=1).first() 28 book_obj.authors.add(author_obj) 29 ''' 30 add给第三张关系表添加数据,括号内既可以传数字,也可以传对象,并且都支持多个 31 book_obj.authors.add(2,3) 32 ''' 33 34 # 删除--方式一: 35 book_obj = models.Book.objects.filter(pk=2).first() 36 book_obj.authors.remove(2) # 也支持同时删除多个 37 # 删除--方式二:对象 38 book_obj.authors.remove(3) # remove给第三张关系表删除数据,括号内既可以传数字,也可以传对象,并且都支持多个 39 40 # 修改 set()内必须放一个可迭代对象 41 book_obj = models.Book.objects.filter(pk=1).first() 42 book_obj.authors.set([1, 3]) # 把原理关联作者1,2改为1,3. 可迭代对象了也可以只放一个参数 43 # 这时候主键id也变了,是因为,先把原来的数据删除,然后再创建 44 # 第二种修改方法 45 author_obj = models.Author.objects.filter(pk=2).first() 46 book_obj.authors.set([author_obj]) 47 48 # 清空-----有一本书永久下架了,所有和它关联的数据都应该删除 49 book_obj = models.Book.objects.filter(pk=1).first() 50 book_obj.authors.clear()
。
。
。
【正反向的概念】
概念: 正向 外键字段在我手上,我去查你就是正向 如书查出版社,外键字段在书那里 book>>>>正向>>>>publish 反向 外键字段不在我手上,我去查你就是反向 如出版社去查书,外键字段在书那里 publish<<<方向<<<<book
-----------------------------------------
-----------------------------------------
口诀:正向查询按字段
反向查询按表名小写_set
(多表查询)
子查询----------------------django(基于对象的跨表查询)
1 正向: 2 # 1.查询书籍主键为1的出版社 3 book_obj = models.Book.objects.filter(pk=1).first() 4 # 书查出版社 正向 5 res = book_obj.publish 6 print(res) # 对象:南京出版社 7 8 # 2.查询书籍主键为2的书籍所有作者 9 book_obj = models.Book.objects.filter(pk=2).first() 10 # rqs = book_obj.authors 11 # print(rqs) # 拿到的是:app01.Author.None, 12 rqs = book_obj.authors.all() 13 print(rqs) # 拿到两个作者对象: < QuerySet[ < Author: Author object(2) >, < Author: Author object(3) >] > 14 15 # 3.查询作者为jason的电话号码 16 author_obj = models.Author.objects.filter(name='jason').first() 17 rws = author_obj.author_detail.phone 18 print(rws) # 120 19 20 21 ------------------------------------ 22 ------------------------------------ 23 反向 24 # 4.查询出版社为南京出版社的书籍名称 25 publish_obj = models.Publish.objects.filter(name='南京出版社').first() 26 # 出版社查书---表名小写_set 反向 27 res = publish_obj.book_set.all() 28 print(res) 29 30 # 5.查询作者为jason写过的书 31 author_obj = models.Author.objects.filter(name='jason').first() 32 ras = author_obj.book_set.all() 33 print(ras) 34 35 # 6.查询手机号是120的作者名字 36 author_obj = models.Author.objects.filter(author_detail__phone=120).first() 37 print(author_obj.name) 38 ''' 39 基于对象反向查询的时候 40 当你的查询结果可以有多个的时候,就必须加_set.all() 41 当查询结果只有一个的时候,不需要加_set.all() 42 '''
连表查询-------------------django(基于双下划线的跨表查询)
1 # 1。一行代码查询出jason的手机号__xxx 2 res = models.Author.objects.filter(name='jason').values('author_detail__phone').first() 3 print(res) 4 5 # 2.查询书籍主键为1的出版社名称和书籍名称 6 rzs = models.Book.objects.filter(pk=1).values('title', 'publish__name').first() 7 print(rzs) 8 # 不用.book去操作,第二种方法 9 rxs = models.Publish.objects.filter(book__id='1').values('name', 'book__title').first() 10 print(rxs) # {'name': '南京出版社', 'book__title': '三国演义'} 11 12 # 3.查询书籍主键为1的作者姓名 13 rcs = models.Book.objects.filter(pk=1).values('authors__name').first() 14 print(rcs) 15 # 不用.book去操作,第二种方法 16 rvs = models.Author.objects.filter(book__id='1').values('name').first() 17 print(rvs) # {'name': 'jason'} 18 19 # 4.查询出jason的手机号和作者姓名,但是不用.Author 20 rbs = models.AuthorDetail.objects.filter(author__name='jason').values('phone', 'author__name') 21 print(rbs) 22 ''' 23 models.AuthorDetail.objects.filter(author__name='jason') 拿作者姓名是jason的作者详情 24 ''' 25 26 # 5.查询书籍主键是1的作者的手机号 27 # book author author_detail,先跨到作者表去拿作者手机号 28 rns = models.Book.objects.filter(pk='1').values('authors__author_detail__phone') 29 print(rns)
。
。
。
【聚合查询】
1 聚合查询(聚合函数的使用):需要先导入5个函数,基本上都配合分组使用 2 不想分组,还想查询的用---aggregate 3 4 只要跟数据库相关的模块,基本上都在django.db.models里面 5 6 from django.db.models import Avg, Max, Min, Sum, Count 7 8 # 1.查询书籍的平均价格, 9 res = models.Book.objects.aggregate(Avg('price')) 10 print(res) 11 # 上述方法一次性使用 12 res = models.Book.objects.aggregate(Avg('price'), Max('price'), Min('price'), Sum('price'), Count('pk')) 13 print(res)
。
。
【分组查询】
1 # 分组查询 关键字:annotate 2 # 按什么分组:models.后面是什么就是按照什么分组 3 # 1.统计每一本是的作者个数 4 res = models.Book.objects.values('title').annotate(count=Count('authors')) 5 print(res) 6 # 方式二 7 rqs = models.Book.objects.annotate(author_num=Count('authors')).values('title', 'author_num') 8 print(rqs) 9 # 方式三: 10 rws = models.Book.objects.annotate(author_num=Count('authors__id')).values('title', 'author_num') 11 print(rws) 12 13 # 2.统计每个出版社卖的最便宜的书的价格 14 rrs = models.Publish.objects.annotate(min_price=Min('book__price')).values('name', 'min_price') 15 print(rrs) 16 17 # 3.统计不止一个作者的图书 18 rts = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1).values('title', 19 'author_num') 20 print(rts) 21 22 # 4.查询每个作者出的书的总价格 23 rys = models.Author.objects.annotate(sum_price=Sum('book__price')).values('name', 'sum_price') 24 print(rys) 25 ''' 26 如果像按照指定的字段进行分组,那么该如何处理呢? 27 models.Book.objects.values('price).annotate() 28 29 '''
。
。
【F和Q查询】
1 ''' 当需要字段和字段作比较的时候用F查询,当查询条件也就是等号右边不是明确的,查询条件也需要从数据库中获取 就需要使用F查询 ''' 2 3 ''' 当查询条件是 或 的时候 用Q查询,因为默认的filter参数都是且的关系 ''' 4 5 6 F查询 7 8 # 1.查询出卖出大于库存数的书籍 9 # F查询:能够获取表中某个字段对应的数据,F不能够直接做到字符串的拼接 10 from django.db.models import F 11 12 res = models.Book.objects.filter(maichu__gt=F('kucun')) 13 print(res) 14 15 # 2.将所有书籍的价格提升50元 16 rzs = models.Book.objects.all().update(price=F('price') + 50) 17 print(rzs) 18 19 # 3.将所有书的名称后面加上爆款两个字,----F不能够直接做到字符串的拼接 20 from django.db.models import Value 21 from django.db.models.functions import Concat 22 23 models.Book.objects.update(title=Concat(F('title'), Value('爆款'))) 24 25 ======================= 26 Q查询 27 28 # 1.查询卖出书大于100,或者价格小于200的书籍 29 # filter()内多个参数是and关系 30 from django.db.models import Q 31 32 res = models.Book.objects.filter(Q(maichu__gt=100), Q(price__lt=200)) # , 和and同义 33 rqs = models.Book.objects.filter(Q(maichu__gt=100) | Q(price__lt=200)) # |是or同义 34 rws = models.Book.objects.filter(~Q(maichu__gt=100) | Q(price__lt=200)) # ~和not同义 35 print(res) 36 print(rqs) 37 print(rws) 38 39 # Q的高阶用法,能够将查询条件的左边也变成字符串的形式 40 q = Q() 41 # and可以修改为or 42 q.connector = 'or' 43 q.children.append(('maichu__gt', 100)) 44 q.children.append(('price__lt', 200)) 45 rds = models.Book.objects.filter(q) # 默认还是and关系 46 print(rds)
。
。
。
【django开启事务】
1 事务(ACID): 2 数据库事务指的则是作为单个逻辑工作单元执行的一系列操作(SQL语句) 功能: 3 1、为数据库操作提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性 4 的方法。 5 2、当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干 6 扰。 7 这些操作要么全部执行,要么全部不执行。 8 9 10 事务的四大特性? 11 原子性 Atomicity 12 事务作为一个整体,包含在其中对于数据库的操作,要么全部执行,要么全部不执行。 13 例如:A给B转了100,A余额减100,刚转完系统崩溃,B收到钱款这一操作没有执行, 14 则整个事务回滚,100元退还到A的余额 15 16 一致性 Consistency 17 事务应该确保数据库从一致状态转到另一个一致状态。 18 例如:转账行为中,一个人减了50元,另外一个人就应该加上这50元,而不能是40元。 19 其他一致状态的含义是数据库中的数据应满足完整性约束,例如字段约束不能为负数, 20 事务执行完毕后的该字段也同样不是负数。 21 22 隔离性 Isolation 23 多个事务并发执行时,一个事务的执行应该不受其他事务执行的影响。 24 举例:A给B转100元和C给B转100元是独立的。 25 26 持久性 Durability 27 成功执行的事务产生的结果应该被永久保留在数据库中
1 from django.db import transaction 2 3 # atomic原子性 4 with transaction.atomic(): 5 ... 6 # 在with代码块内书写的所有orm操作都属于同一种事务 7 print('执行其他操作')
。
。
。
【常用字段】
1 AutoField 自增 字段类型 2 括号内常见参数: primary_key=True 3 ----------------------- 4 CharField 对应到数据库里面是varchar字段类型 5 括号内常见参数: max_length 6 ---------------------------------------------- 7 数字相关字段类型: 8 IntegerField 9 BigIntergerField 10 11 DecimalField 12 括号内常见参数: max_digits decimal_places 13 ---------------------------------------------- 14 日期相关字段类型: 15 DateField ---date 16 括号内常见参数: auto_now auto_now_add 17 DateTimeField ---datetime 18 括号内常见参数: auto_now auto_now_add只记录创建记录的时间 19 ---------------------------------------------- 20 布尔值字段类型: 21 22 BooleanField 23 传布尔值自动存0或1 24 ---------------------------------------------- 25 文本字段类型: 26 27 TextField 28 存储大段文本,没有字数限制 29 ---------------------------------------------- 30 邮箱字段类型: 31 32 EmailField 33 存储邮箱格式数据 34 ---------------------------------------------- 35 文件对象字段类型: 36 37 FileField 38 传文件对象 自动保存到提前配置好的路径下并存储该路径信息!! 39 参数: 40 upload_to = "" 上传文件的保存路径 41 storage = None 42 # 存储组件,默认django.core.files.storage.FileSystemStorage 43 ----------------------------------------------------------- 44 ORM还支持用户自定义字段类型: 45 46 class MyCharField(models.Field): 47 def __init__(self, max_length, *args, **kwargs): 48 self.max_length = max_length 49 super().__init__(max_length=max_length, *args, **kwargs) 50 51 def db_type(self, connection): 返回真正的熟练类型及各种约束条件 52 return 'char(%s)' % self.max_length 53 54 55 class User(models.Model): 56 name = models.CharField(max_length=32) 57 info = MyCharField(max_length=64)
(ORM常用字段参数)
1 primary_key 主键 2 verbose_name 注释 3 max_length 字段长度 4 max_digits 小数总共多少位 5 decimal_places 小数点后面的位数 6 auto_now 每次操作数据自动更新事件 7 auto_now_add 首次创建自动更新事件后续不自动更新 8 null 允许字段为空 9 default 字段默认值 10 unique 唯一值 11 db_index 给字段添加索引 12 choices 当某个字段的可能性能够被列举完全的情况下使用 13 14 to 关联表 15 to_field 关联字段(不写默认关联数据主键) 16 on_delete 当删除关联表中的数据时,当前表与其关联的行的行为。 17 1、models.CASCADE 18 级联操作,当主表中被连接的一条数据删除时,从表中所有与之关联的数据同时被删除 19 2、models.SET_NULL 20 当主表中的一行数据删除时,从表中所有与之关联的数据的相关字段设置为null,此时注意定义外键时,这个字段必须可以允许为空 21 3、models.PROTECT 22 当主表中的一行数据删除时,由于从表中相关字段是受保护的外键,所以都不允许删除 23 4、models.SET_DEFAULT 24 当主表中的一行数据删除时,从表中所有相关的数据的关联字段设置为默认值,此时注意定义外键时,这个外键字段应该有一个默认值 25 5、models.SET() 26 当主表中的一条数据删除时,从表中所有的关联数据字段设置为SET()中设置的值,与models.SET_DEFAULT相似,只不过此时从表中的相关字段不需要设置default参数 27 6、models.DO_NOTHING 28 什么都不做,一切都看数据库级别的约束,注数据库级别的默认约束为RESTRICT,这个约束与django中的models.PROTECT相似
。
。
。
【orm补充】
(only与defer 关键字 优化查询数据的时间)
原来用all,要查所有字段的数据,然后封装到一个个对象里面去
现在用only就可以只查需要的几个字段数据,封装到一个个对象里面去,
这样查询数据的时间肯定减少了!!
1 关键字 only 2 3 感觉像是all的升级版 all拿到的对象,里面有所有的字段名及对应的值 4 only拿到的对象,里面只有括号里面指定的字段名及对应的值 5 后续用对象点括号里面有的字段名不走sql查询,点没有的字段名会走sql查询!!! 6 7 only方法的作用是:可以将括号里面所列举的字段封装到数据对象里面, 8 当数据对象点击这些字段的时候是不会走sql查询的。 9 10 但是如果用数据对象去点击括号里面所没有填写的字段时,可以拿到数据,但是每点一次都会走一次sql数据库查询。 11 12 需求升级:只获取指定字段的数据,并且结果还是一个的数据对象!!! 13 14 res = models.Book.objects.only('title', 'price') 15 16 print(res) # queryset [数据对象、数据对象] 17 for obj in res: 18 print(obj.title) 19 print(obj.price) # 点击括号内填写的字段 不走SQL查询 20 # 这种情况下用only获取到的对象,可以直接点击它括号里面的字段,不会走sql语句 21 22 print(obj.publish_time) 23 # 也可以点击括号内没有的字段,也能获取到数据 ,但是会走SQL查询 24 25 26 ========================= 27 关键字 defer 和only作用相反 28 29 拿到的对象里面除了括号里面指定的字段名数据没有 ,其他的字段名数据都有!!! 30 后续用对象点括号里面有的字段名就会走sql查询, 31 点括号里面没有的字段名,不走sql查询!!! 32 33 34 res = models.Book.objects.defer('title', 'price') 35 print(res) # queryset [数据对象、数据对象] 36 for obj in res: 37 print(obj.title) # 点击括号内填写的字段 走SQL查询 38 print(obj.price) 39 print(obj.publish_time) # 点击括号内没有的字段获取数据 不走SQL查询
。
。
(select_related与prefetch_related 优化的sql执行的次数)
1 select_related 底层是先连表后查询,再封装到对象里 2 3 res = models.Book.objects.all() 4 for obj in res: 5 print(obj.title) # 不走SQL查询,all的sql查询将所有数据都塞到每个对象里面了 6 7 print(obj.publish.name) # 当用数据对象点关联的出版社表里面的数据时,每次查询都需要走SQL查询 8 9 ------------------------------------------------ 10 ------------------------------------------------ 11 12 res = models.Book.objects.select_related('publish') # 底层是先连表后查询封装 13 # 括号内支持填写一对多外键字段 14 # 提前先连表后查询数据,最后封装到一个个对象里面去! 15 for obj in res: 16 print(obj.publish.name) # 不再走SQL查询!!! 17 18 # 先将书表和出版社表拼到一起,然后把大表里面的所有数据封装到一个个书籍对像里面去 19 # 这样拿到的对象通过点的方式既可以点书表里面的所有字段,也可以点出版社表里面的所有字段 20 # 所以就不需要再走sql查询了!!! 21 22 ------------------------------------------------ 23 ------------------------------------------------ 24 25 res = models.Book.objects.select_related('authors') 26 # 括号内不支持填写多对多外键字段!!! 27 28 29 res1 = models.Author.objects.select_related('author_detail') 30 # 括号内也支持填写一对一外键字段 31 print(res1) 32 33 34 ============================ 35 prefetch_related 底层是先子查询,再封装到对象里 36 37 res = models.Book.objects.prefetch_related('publish') 38 # 底层是子查询,总共执行两条sql语句,第一条sql查询的结果作为第二条sql的查询条件 39 for obj in res: 40 print(obj.publish.name) # 不再走SQL查询! 41 42 # prefetch_related() 括号里面也是只能填写外键字段(除了多对多) 43 # 作用是 先把书表里面的所有数据查出来,然后基于书里面publish_id对应的值,再到出版式表里面,把对应的数据再查出来,之后封装起到一个个的书籍对象里面去
分类:
django
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现