zoukankan      html  css  js  c++  java
  • orm查询优化 MTV和MVC模型 字段的chioces参数 Ajax

    一、ORM查询优化

    • 遵循能少走一次数据库就少走一次,即一次查询操作中能少用SQL查询语句就尽量少用。

    1. all()查询

    • 惰性查询 减少不必要的数据库操作 降低数据库的压力

    • res = models.Book.objects.all()
      # 针对这行代码,如果不使用res,则不会执行数据库查询的。
      
      

    2. only()/defer()方法

    (1)only()方法

    • only()括号内放字段 查询结果是一个列表套一个个的数据对象,即queryset对象。

    • 这些数据对象点括号内的字段不会再查询数据库,直接就是对象获取属性

    • 也支持点括号内没有的字段,但是每点一次就会重新走一次数据库查询,此时查询效率极低。

    • 实例

      res = models.Book.objects.only('title')
      print(res)
      for i in res:
          print(i.title)  # 只会走最初的那一次,这行不走数据库
          print(i.price)  # 除了最初查询走的那一次,每到这一行都会再走一次数据库进行查询
      

    (2)defer()方法

    • defer()only()是互为反操作

    • defer()括号内放什么字段 查询出来的对象就没有该字段属性

    • 如果你要对象点括号内的字段,每点一次就要重新走一次数据

    • 而你如果点击了非括号内的字段,就不会走数据库,仅仅是对象点属性的操作

    • 实例

    res = models.Book.objects.defer('title')
    print(res)
    for i in res:
       print(i.title)  # 除了最初查询走的那一次,每到这一行都会再走一次数据库进行查询
       print(i.price)  # 只会走最初的那一次,这行不走数据库
    
    • select_related原理是联表查询

    • select_related括号内只能放外键字段 并且外键字段的类型只能是一对多 或者 一对一 不能是多对多

    • 内部是自动联表操作,会将括号内外键字段所关联的表,与当前表自动拼接成一张表

    • 然后将表中的数据一个个查询出来封装成一个个的对象,这样做的好处就在于跨表也不需要重复的走数据库了,减轻数据库的压力

    • 耗时:主要在联表时耗时(数据库层的操作)

    • 实例

    res = models.Book.objects.select_related('publish')  # publish为外键字段
    print(res)
    for i in res:
      print(i.title)  # title为普通字段 , 只是对象点属性获取属性值,不走数据库
      print(i.publish)  # 只是对象点属性获取属性值,不走数据库
    
    • prefetch_related原理是子查询

    • 自动帮你按步骤查询多张表,然后将查询的结果封装到对象中,用户的感觉好像还是联表操作

    • 括号内支持传多个外键字段,并且没有类型限制

    • 特点:每放一个外键字段,就会多走一条sql语句,多查询一张表

    • 耗时:查询的次数上的耗时

    • 实例

    res = models.Book.objects.prefetch_related('publish','authors')  # publish 和 authors都是外键字段, publish是一对多的外键字段,authors是多对多的建立第三张表的虚拟外键字段
    print(res)
    for i in res:
       print(i.title)  # 只是对象点属性获取属性值,不走数据库
       print(i.publish)  # 只是对象点属性获取属性值,不走数据库
    

    (3)select_related()/prefetch_related()的优缺点

    • 没有谁比谁好,结合实际情况,使用不同方法。
    • 如两张表都太大时,联表时会把不需要的一些数据行也连接在一起成一张大表,不但消耗更多的时间,也浪费内存,因为联表是数据库层的操作,所以还会增加数据库的负担。此时,用prefetch_related()方法更好。

    二、MTV与MVC模型

    • 这两个东西都是纯理论,没有特别的意思。

    1. MTV模型

    • MTV

      • M:models
      • T:templates
      • V:views
    • django自称为是MTV框架 本质其实还是MVC

    2. MVC模型

    • MVC
      • M:models
      • V:views
      • C:controller 路由匹配

    三、chioces参数

    • chioces参数的作用是把一些数据信息映射成一个简单的字符串或者数字,在保存数据时只需要保存这些简单的字符串或数字即可,以此可以节省数据库资源。
    • 取值:
      • 只要是choices字段类型,在获取值的时候 统一句式: get_字段名_display() 。 若直接以对象点字段的方式,则获取到的是我们自定义chioces参数的值的每个元组中的第一个元素。
    • 插入数据:
      • 当我们在插入数据时,若插入chioces参数的自定义值中没有的数据,可以插入成功。在使用get_字段名_display()取值时,因为元组中没有第二个元素,不会报错,取值也只会取到第一个元素。这里不是很好理解,看下面的实例。
    • 实例
    # models.py文件中:
    
    class User(models.Model):
        username = models.CharField(max_length=64)
        password = models.IntegerField()
        
        # 自定义chioces参数的值,一个元组就是一个值,元组第一个元素可以为数字,也可以为字符串,以gender字段的字段类型为准。
        gender_choices = (  
            (1,'男'),
            (2,'女'),
            (3,'其他'),
        )
        gender = models.IntegerField(choices=gender_choices)  # chioces参数
        
        
    # views.py文件中:    
        
        # 执行插入操作
        models.User.objects.create(username='tank',password=123,gender=1)
        models.User.objects.create(username='nick',password=123,gender=4)  # 可以插入数据成功
        
        # 执行查询操作
        user_obj1 = models.User.objects.filter(username='tank').first()
        user_obj2 = models.User.objects.filter(username='nick').first()
        
        # 打印信息
        print(user_obj1.get_gender_display())  # 结果是: 男
        print(user_obj2.get_gender_display())  # 结果是: 4
    

    四、Ajax

    • Ajax 不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术

    • Ajax 特点:异步提交,局部刷新

    • AJAX 最大的作用是在不重新加载整个页面的情况下,可以与服务器交换数据并更新网页的部分内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)-

    • 题外话:

      • 每家公司都会有属于这家公司独有的内部管理软件
      • 专门用来开发企业内部管理软件框架 ——》 odoo
      • odoo框架内部功能实现全部依赖于python2

    1. Ajax语法

    (1)起手语法

    起手:
    $.ajax({
       # 书写代码
    			})
    

    (2)Ajax基本语法结构

    • <scrip>
      
      $.ajax({
      		url:'',  // 数据提交的后端地址  不写就是往当前页面提交  也可以写后缀 也可以写全称  跟form表单的actions参数一样
      		type:'post',  // 提交方式  默认是get请求
      		data:{'i1':$('#d1').val(),'i2':$('#d2').val()},  // 提交的数据
      		success:function (recv_data) {  // 形参recv_data就是异步提交之后后端返回结果
      			$('#d3').val(recv_data)  // 回调机制需要做的事情
      		   }
      		})
      
      </scrip>
      
    • 实例

    // 前端代码:
    
    $.ajax({
    		url:'',  // 数据提交的后端地址  不写就是往当前页面提交  也可以写后缀 也可以写全称  跟form表单的actions参数一样
    		type:'post',  // 提交方式  默认是get请求
    		data:{'i1':$('#d1').val(),'i2':$('#d2').val()},  // 提交的数据
    		success:function (recv_data) {  // 形参recv_data就是异步提交之后后端返回结果
    			$('#d3').val(recv_data)  // 回调机制需要做的事情
    		   }
    		})
    
    
    // 后端代码:
    
    def xxx(request):
        print(request.is_ajax())  # 判断当前请求是否是ajax请求,打印结果: True
        # print(request.POST)  # ajax发送的post请求 普通的键值对也在request.POST中获取
        if request.is_ajax():
            i1 = request.POST.get('i1')
            i2 = request.POST.get('i2')
    
            res = int(i1) + int(i2)
            return HttpResponse(res)  # 给异步回调函数 success
            # return render(request,'xxx.html')  # 给异步回调函数 success
            # return redirect('https://www.baidu.com')  # 给异步回调函数 success
        return render(request,'xxx.html')
    
    • 注意:一旦你使用了ajax,django中必知必会三板斧(render/HttpResponse/redirect)都不再作用与页面,而是与recv_data交互,即这三个方法返回到前端的数据都被接收中recv_data中

    五、前端传输数据的编码格式

    • 前端发到后端的数据都有数据编码格式,针对不同的数据,后端会自动进行不同的处理
    • 前端中,只要你的数据满足urlencoded格式,不管你当前的编码格式是什么,django后端都会自动解析,并且根据你的提交方式帮你封装到request.GET或request.POST
      • urlencoded编码格式对应的数据的格式:username=jason&password=123

    1. 常见的编码格式

    1. urlencoded
    2. formdata
    3. application/json

    2. form表单发送数据的编码格式

    • form标签的控制编码格式的属性:enctype

    (1)urlencoded编码格式

    • form表单默认编码格式是urlencoded

    • urlencoded编码格式对应的数据格式:

      • username=jason&password=123
        
    • django后端针对urlencoded数据,会自动解析,帮你封装到request.POST

    (2)formdata编码格式

    • 传文件时用的编码格式
    • 传文件必须做到两件事:
      • 必须将其默认的urlencoded换成formdata
      • 提交数据方式改为post
    • 针对formdata格式的数据,你在浏览器上是无法查看到,因为这时的提交方式肯定是post
    • 如果你是一个文件对象,django后端也会自动识别帮你放到request.FILES

    (3)json格式

    • form表单无法发送json格式的数据 你要想法 你只能借助于ajax。

    3. ajax发送数据的编码格式

    • ajax能够发送3种格式的数据:
      • urlencoded
      • formdata
      • application/json

    (1)urlencoded编码格式

    • ajax默认的编码格式也是urlencoded 也就意味着后端django也是会自动解析,并且帮你封装到request.POST`中

    (2)formdata编码格式

    • 文件对象的数据,django后端会自动识别并存放在request.FILES

    • Ajax传文件的实例:

    • 牢记实例中的1, 2, 3, 4 四点。

    • 以下MyFormData添加的前3条数据在后端会自动存放在request.POST中,最后一个文件数据会在后端自动存放在request.FILES中。

    <scrip>
        // 传文件
        $('#d1').click(function () {
            // 1.先生成一个内置对象
            var MyFormData = new FormData();
            // 2. 先添加普通的键值
            MyFormData.append('username','jason');  // 添加了一组普通的键值对
            MyFormData.append('password','123');
            MyFormData.append('hobby',['read','run']);
            // 3. 添加文件数据
            MyFormData.append('myfile',$('#d2')[0].files[0]);  // 如何获取input框中文件对象$('#d1')[0].files[0]
        
        	// ajax基本语法结构
            $.ajax({
                url:'',
                type:'post',
                data:MyFormData,
    
                // 4. 发送文件必须要指定的两个参数(1)(2)
                contentType:false,  // (1)不适用任何编码  MyFormData对象内部自带编码 django后端能够识别
                processData:false,  // (2)不要处理数据
    
                success:function (back_data) {
    					alert(back_data)	// 回调机制需要做的事情
                }
    
            })
        })
        
    </scrip>
    

    (3)application/json编码格式

    • django后端针对json格式的数据,不会做任何处理,数据怎么来的,只会原封不动的放到request.body,需要你自己手动处理。(即到后端还是二进制类型的json格式的数据)

    • ajax传输json格式数据实例:

    • 注意:实例中的1, 2 两点

    <scrip>
    $('#d1').click(function () {
            $.ajax({
                url:'',
                type:'post',
                contentType:'application/json',  // 1.编码格式写法
                data:JSON.stringify({'username':'jason','password':'123'}),  // 2.序列化
                success:function (back_data) {
                    alert(back_data)
                }
            })
        })
    </scrip>   
    
    • 后端对前端的ajax传输过来的json格式的数据的反序列化
    # 因为ajax传输过来的json格式的数据是二进制类型的json格式,所以:
    
    # 方式一:
    import json
    json_data = ajax_data.decode('utf-8')
    data = json.loads(json_data)
    
    # 方式二:直接使用json.loads , 他会直接把二进制也一起转。
    
    data = json.loads(ajax_data)
    

    六、后端数据的序列化

    • 在实际开发环境中,针对前后端分离的模式,因为此时不能使用django的模板语法,后端返回到前端的数据需要非常多、非常清晰,并且是json格式的数据。如:要返回当前数据来自哪张表,数据要有描述即字典类型,还有等等,我们此时就需要自己手动书写,这样就会非常麻烦,也不保证没有缺漏的数据。

    • 针对上面的问题,通过django中的内置模块serializers就可以完美解决了。

    • 实例:

      from app01 import models
      from django.core import serializers
      
      # 序列化目的  将数据整合成一个大字典形式 方便数据的交互
      def zzz(request):
          
      	user_queryset = models.User.objects.all()
      	res = serializers.serialize('json',user_queryset)
      	return HttpResponse(res)
      
  • 相关阅读:
    使用vscode 用git 拉取代码,提示:在签出前,请清理存储库工作树
    区分手机端和pc端加载不同的样式
    关于vue的代码规范
    各种名词汇总整理
    ZB埋点汇总
    项目实战 OLAP数据提取
    大数据intern_1总结:数据埋点以及SQL复习
    leetcode 343+279+91+64+70 动态规划
    leetcode 241 加优先级括号
    leetcode 17+79+93+46+47+77+39+40+78+90+131+37 回溯法
  • 原文地址:https://www.cnblogs.com/Mcoming/p/11960875.html
Copyright © 2011-2022 走看看