## ORM查询优化,事务,ajax ## 内容概要 - Q查询进阶操作 - ORM查询优化 - ORM事务操作 - ORM常用字段类型 - ORM常用字段参数 - ORM三种创建多对多的方式 - Ajax请求 ## 内容详细 Q查询进阶操作,默认and连接 ```python from django.db.models import Q q_obj = Q() # q_obj.connector = 'or' q_obj.children.append(('pk', 1)) # 默认连接符是and q_obj.children.append(('publish_id',1)) res = models.Book.objects.filter(q_obj) print(res) ```  ```python from django.db.models import Q q_obj = Q() q_obj.connector = 'or' # 修改连接符 为or q_obj.children.append(('publish__gt', 2)) q_obj.children.append(('title__contains','三国'))#支持添加多个 res = models.Book.objects.filter(q_obj) # 查询对象支持填写Q对象 print(res) ```  ## ORM查询优化 1. ORM的查询默认都是惰性查询 ```python res = models.Book.objects.only('title','price').all() print('123') # 按照以往的经验代码走到之这里上面的肯定就执行完毕了 ```  2. ORM的查询自带分页处理 ```python res = models.Book.objects.only('title','price').all() print('123') # 按照以往的经验代码走到之这里上面的肯定就执行完毕了 print(res) ```  3. only与defer ### only 数据对象+含有指定字段对应的数据 点括号内存在的字段 ```python res = models.Book.objects.only('title','price') print(res) # 这里如果放在for循环queryset上面打印就会先查一下数据分页处理,然后下面for循环查的时候直接查完,不在分页 for obj in res: print(obj.price) # 点上面填写的字段时候只会查一次数据库 ```  不会每次查询 点括号内不存在的字段 ```python res = models.Book.objects.only('title','price') for obj in res: print(obj.publish) # 点括号内不存的字段时候,每点一次,就查询一次sql语句 ```  会每次查询 ### defer 点括号内存在的字段 ```python res = models.Book.objects.defer('title','price') for obj in res: print(obj.title) # 点括你有的字段,每点一次查询一次 ```  点括号内不存的字段 ```python res_query = models.Book.objects.defer('title','price') for obj in res_query: print(obj.pk) # 点括号内不存在的字段,只查询一次 ```  点击外键字段在括号内 ```python res_query = models.Book.objects.defer('title','price','publish') for obj in res_query: print(obj.publish) # 在点击外键时候,外键在括号内,查询次数根据子查询在查一遍,相当于元数据的一倍 ```  点击外键字段不在括号内 ```python res_query = models.Book.objects.defer('title','price') for obj in res_query: print(obj.publish) # 点外键不在括号内时,只查询数据个数次数 ```  #### only与defer小总结: 使用only时,点的字段在括号内,就只查询一次SQL语句,点的字段不在括号内,就会每次查询都走SQL语句 使用defer时,点的字段在括号内,每次查询都走SQL语句,点的字段不在括号内,就只走一次SQL语句 ### select_related与prefetch_related #### select_related 不能放多对多字段 ```python res_query = models.Book.objects.select_related('authors') # 只能放外键字段,并且不能放多对多字段 print(res_query) ```  先连表后查询封装 ```python res_query = models.Book.objects.select_related('publish') # 括号内只能使用一对对外键和者,一对一外键 for obj in res_query: print(obj.publish.name) # 底层使用的连表操作,执行走一次SQL语句 ```  #### prefetch_related ```python res_query = models.Book.objects.prefetch_related('authors') # 括号内所有外键都可使用 for obj in res_query: # 底层使用的是子查询操作 print(obj.authors.all()) #查询字段值按照ORM跨表查询 print(obj.title) ```  ## ORM事务操作 1. 事务的四大特性(ACID) 原子性 一致性 隔离性 持久性 2. 相关SQL关键字 start transactions; roll back; commit; save point; 3. 相关重要概念 脏读,不可重复读,幻读,mvcc多版本控制、 再没有开启事务时,只要执行sql成功,下面错误不影响上面sql语句 ```python def transcation(request): models.Publsh.objects.create(name='哈哈哈',address='1231') print('执行SQL完毕') asdasdasdas return HttpResponse('123') ```  django orm提供了至少三种开启事务的方式 方式1:配置文件数据相关添加键值对 全局有效 ```python 'ATOMIC_REQUESTS': True, # 每次请求所涉及到的ORM操作为一个事务 def transcation(request): models.Publsh.objects.create(name='撒旦胡卡',address='123') print('执行SQL完毕') asdasdasdas return HttpResponse('123') ```  只要再一个视图函数中或者视图类中的一个请求中,都同属一个事务,只要出现错误就回滚到之前的状态 方式2:装饰 局部有效 ```python @transaction.atomic #局部有效 def transcation(request): models.Publsh.objects.create(name='撒旦胡卡', address='123') print('执行SQL完毕') asdasdasdas return HttpResponse('123') ```  方式3:上下文管理 局部有效 ```python def ttt(request): print(123) with transaction.atomic(): models.Publsh.objects.create(name='撒旦胡卡', address='123') print('执行SQL完毕') asdasdasdas return HttpResponse('123') ```  ## ORM常用字段类型 ```python class Test1(models.Model): id = models.AutoField(primary_key=True) # 主键字段 int自增列,必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列。 var1 = models.CharField(max_length=32) # 字符串字段,必须指定max_length 字符类型,必须提供max_length参数, max_length表示字符长度。 var2 = models.IntegerField() # 整数字段最大11位 一个整数类型,范围在 -2147483648 to 2147483647。(一般不用它来存手机号(位数也不够),直接用字符串存,) var3 = models.BigIntegerField() # 大整数字段 var4 = models.DecimalField(max_digits=8, decimal_places=2) # 小数字段 var5 = models.DateTimeField(auto_now_add=True) # 年月日时分秒,时间字段 var6 = models.DateField(auto_now=True) # 年月日,时间字段 var7 = models.BooleanField() # 布尔字段 传布尔值自动存0或1 var8 = models.TextField() # 存储大段文本 无需传入max_length参数 var9 = models.EmailField() # 储存邮件格式数据 var10 = models.FileField() # 传文件对象 自动保存到提前配置好的路径下并存储好该路径信息 ``` ORM还支持用户自定义字段类型 ```python class MyCharField(models.Field): def __init__(self,*args,**kwargs): super().__init__(*args,**kwargs) def db_type(self, connection): return 'char(%s)' % self.max_length class Usera(models.Model): name = models.CharField(max_length=32) info = MyCharField(max_length=10) ``` ## ORM常用字段参数 ```python primary_key 主键 verbose_name 注释 max_length 字段长度 max_digits 小数总共多少位 decimal_places 小数点后面的位数 auto_now 每次操作数据自动更新事件 auto_now_add 首次创建自动更新事件后续不自动更新 null 允许字段为空 default 字段默认值 unique 唯一值 db_index 给字段添加索引 choices 当某个字段的可能性能够被列举完全的情况下使用 性别、学历、工作状态、... class User(models.Model): name = models.CharField(max_length=32) info = MyCharField(max_length=64) # 提前列举好对应关系 gender_choice = ( (1, '男性'), (2, '女性'), (3, '其他'), ) gender = models.IntegerField(choices=gender_choice,null=True) user_obj = User.objects.filter(pk=1).first() user_obj.gender user_obj.get_gender_display() to 关联表 to_field 关联字段(不写默认关联数据主键) on_delete 当删除关联表中的数据时,当前表与其关联的行的行为。 1、models.CASCADE 级联操作,当主表中被连接的一条数据删除时,从表中所有与之关联的数据同时被删除 2、models.SET_NULL 当主表中的一行数据删除时,从表中所有与之关联的数据的相关字段设置为null,此时注意定义外键时,这个字段必须可以允许为空 3、models.PROTECT 当主表中的一行数据删除时,由于从表中相关字段是受保护的外键,所以都不允许删除 4、models.SET_DEFAULT 当主表中的一行数据删除时,从表中所有相关的数据的关联字段设置为默认值,此时注意定义外键时,这个外键字段应该有一个默认值 5、models.SET() 当主表中的一条数据删除时,从表中所有的关联数据字段设置为SET()中设置的值,与models.SET_DEFAULT相似,只不过此时从表中的相关字段不需要设置default参数 6、models.DO_NOTHING 什么都不做,一切都看数据库级别的约束,注数据库级别的默认约束为RESTRICT,这个约束与django中的models.PROTECT相似 ``` ## Ajax 异步提交 局部刷新 ajax不是一门新的技术并且有很多版本 我们目前学习的是jQuery版本(版本无所谓 本质一样就可以) AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。 - 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求; - 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。 基本语法 ```python += ``` ## Content-Type #### urlencoded ajax默认的编码格式、form表单默认也是 数据格式 xxx=yyy&zzz=bbb&aaa=ccc django后端会自动处理到request.POST中 #### formdata django后端针对普通的键值对还是处理到request.POST中 但是针对文件会处理到request.FILES中 #### application/json form表单不支持 ajax可以 ```python 后端需要从request.body中获取并自己处理 ``` ## ajax携带文件数据 ```python 后端还是从request.FILES中获取文件 ``` ## Ajax补充说明 主要是针对回调函数args接收到的响应数据 1. 后端request.is_ajax() 用于判断当前请求是否是ajax发出 2. 后端返回的三板斧都会把args接收不在影响整个浏览器页面 3. 选择使用ajax做前后端交互的时候 后端一般返回的都是字典数据 ```python user_dict={'code':10000,'username':'张三','age':29} ``` ajax自动反序列化后端的json格式的bytes类型数据 ```python dataType:'json', ```  Last modification:December 27th, 2022 at 09:26 pm © 允许规范转载 Support 如果觉得我的文章对你有用,请随意赞赏 ×Close Appreciate the author Sweeping payments
Comment here is closed