zoukankan      html  css  js  c++  java
  • Django 07

    ORM查询优化

    • 就是要尽可能减少对数据库的访问次数

    only与defer(单表)

    • only方法内传入是什么字段, 则拿到的对象就只具有什么属性, 如果获取对象的其他属性, 也可以拿到, 只不过内部要再访问数据库进行查询
    • defer方法内传入什么字段, 则拿到的对象就不具有什么属性, 如果获取对象的该属性, 也可以拿到, 只不过内部要再访问数据库进行查询
    • only与defer互为反关系
    # only
    book_obj = models.Book.objects.filter(pk=1).only('title').first()
    print(book_obj.title)  # 直接获取
    print(book_obj.price)  # 需要访问数据库查询
    
    # defer
    book_obj = models.Book.objects.filter(pk=1).defer('title').first()
    print(book_obj.title)  # 需要访问数据库查询
    print(book_obj.price)  # 直接获取
    

    select_related与prefetch_related(跨表)

    • _related: 表明是和 "表关系" 相关的方法

    • select_related 方法内部是自动连表操作, 会将传入的外键字段关联的表, 与当前的表拼接起来, 支持一对一和一对多表关系, 支持传入多个外键字段

    • prefetch_related 内部是子查询操作, 按步骤查询多张表, 支持多对多表关系, 支持传入多个外键字段, 且每增加一个字段, 查询次数增加一次

    • select_related方法耗时在连表上, 当表比较大的时候, 连表会比较耗时

    • prefetch_related方法耗时在查询次数上

    # select_related
    # 括号内只能放外键字段, 且外键字段类型是能是一对一或者一对多
    # 内部是自动连表操作, 会将括号内外键字段关联的表, 与当前表拼接起来
    # 括号内可以放多个外键字段, 用逗号隔开
    # 耗时: 连表操作上
    book_obj = models.Book.objects.filter(pk=1).select_related('publish').first()
    print(book_obj.publish.name)  # 访问一次数据库
    
    book_obj = models.Book.objects.filter(pk=1).select_related().first()
    print(book_obj.publish.name)  # 访问两次数据库
    
    
    # prefetch_related
    # 内部是子查询操作, 按步骤查询多个表, 然后将查询的结果封装到对象中
    # 括号内可放对个外键字段, 且支持多对多外键
    # 每放一个字段, 就会多查询一张表
    # 耗时: 查询次数上
    book_obj = models.Book.objects.filter(pk=4).prefetch_related('publish', 'authors').first()
    print(book_obj.publish.name)
    print(book_obj.authors.all())
    

    choices参数

    • 针对字段的数据范围是可确定的, 如性别, 学历等, 具有该参数的字段相当于MySQL中的enum枚举
    # User表模型类
    class User(models.Model):
        username = models.CharField(max_length=255)
        password = models.CharField(max_length=255)
        
        # 创建数字和学历对应关系的元祖
        edu_level_choices = (
            (1, 'bachelor'),
            (2, 'master'),
            (3, 'doctor'),
            (4, 'others')
        )
        # 将元祖赋值给choices参数, 字段类型为int
        edu_level = models.IntegerField(choices=edu_level_choices)
     
    
    • 学历数字不在我们定义好的匹配关系中可以正常存储
    +----+----------+----------+-----------+
    | id | username | password | edu_level |
    +----+----------+----------+-----------+
    |  1 | alpha    | 111      |         1 |
    |  2 | bravo    | 111      |         2 |
    |  3 | charlie  | 111      |         3 |
    |  4 | delta    | 111      |         4 |
    |  5 | echo     | 111      |         5 |  
    +----+----------+----------+-----------+
    
    • 当存在对应关系时, 通过 对象.get_choices字段_display() 获取数字对应的值
    • 不存在对应关系时, 该方法也不会报错, 返回的还是该字段对应的数字
    # 1.存在对应关系时
    user_obj1 = models.User.objects.filter(pk=1).first()
    print(user_obj1.edu_level)  # 1
    print(user_obj1.get_edu_level_display())  # bachelor
    
    # 2.不存在对应关系时
    user_obj5 = models.User.objects.filter(pk=5).first()
    print(user_obj5.edu_level)  # 5
    print(user_obj5.get_edu_level_display())  # 5
    
    • 不一定要用数字来建立对应关系, 也可以用字符串

    MTV与MVC模型

    • MTV: models, templates, views
    • MVC: models, views, controller (路由匹配)

    Ajax简介

    • Asyn JavaScript and XML
    • Ajax可以在不页面不刷新情况下, 实现和数据库进行交互
    • 同步交互: 客户端发送一个请求后, 需要等待服务器响应结束后, 才能发送第二个请求
    • 异步请求: 客户端发送一个请求后, 不需要等待服务器响应结束, 就能发送第二个请求
    • 三个必备参数, 一个回调函数
      • url: 提交的地址, 默认是朝当前页面提交
      • type: 提交的方式, 默认是get请求
      • data: 朝后端提交的数据
      • success函数, 函数的参数data接收的后端返回的数据
    # 利用ajax实现页面不刷新的情况下, 现在输入的两个数的和
    
    def ajax(request):
        # 判断当前请求是否ajax请求
        if request.is_ajax():
            # print(request.POST)  # ajax请求发送的数据也在request.POST当中
            v1 = int(request.POST.get('v1'))
            v2 = int(request.POST.get('v2'))
            res = v1 + v2
            return HttpResponse(res)  # 只要有ajax, 三板斧就只返回给ajax的回调函数
        return render(request, 'ajax_page.html')
    
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>ajax test</title>
        <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    </head>
    <body>
    <input type="text" id="d1">+<input type="text" id="d2">=<input type="text" id="d3">
    <button id="d4">提交</button>
    <script>
        $('#d4').on('click', function () {
            // 开启ajax语法句式
            $.ajax({
                url: '',  // 数据提交的后端地址, 不写就是往当前页面提交
                type: 'post',  // 提交方式, 默认还是get请求
                data: {'v1': $('#d1').val(), 'v2': $('#d2').val()},  // 向后端提交的数据
                success: function (data) {  // 形参data是后端返回的结果
                    $('#d3').val(data)
                }
    
            })
        })
    </script>
    </body>
    </html>
    

    前后端传输数据编码格式

    • 三种数据编码格式

      • urlencoded
      • formdata
      • application/json
    • 前端向后端发送数据:

      • a标签 get请求
      • form表单 get/post请求 (urlencoded, form-data)
      • ajax get/post请求 (urlencode, form-data, json)
    • form表单发送文本

      • 编码: Content-Type: application/x-www-form-urlencoded

      • 数据格式: username='bigb'&password='123'

      • 后端针对urlencoded数据, 会自动解析并封装到request.POST中

    • form表单发送文件 ( enctype='multipart/form-data)

      • 编码格式: Content-Type: multipart/form-data
      • 数据格式: 浏览器查看不到
      • 后端对于form-data文件数据, 会自动解析并保存到request.FILES中
    • 前后端交互时候, 一定确保数据格式与编码格式一致

    Ajax传输Json数据格式

    • ajax默认的编码格式也是: Content-Type: application/x-www-form-urlencoded, 因此也会封装到request.POST中

    • ajax默认是发送urlencoded编码格式的数据, 如果想发送json数据格式, 需要加一个参数: contentType: 'application/json'

    $('#d1').on('click', function () {
            $.ajax({
                url: '',
                type: 'post',
                // 指定编码方式为: application/json
                contentType: 'application/json',
                data: JSON.stringify({'username': 'bigb', 'password': '123'}),
                success: function (data) {
                    alert(123)
                }
            })
        })
    
    • django后端会将前端发送的json格式数据(二进制)原封不动的放到request.body中, 注意, 是二进制数据!!!
    def test(request):
        print(request.body)  # b'{"username":"bigb","password":"123"}'
        return render(request, 'test.html')
    

    Ajax传输文件数据

    • ajax传输文件数据需要借助js内置对象FormDate
    • FormData对象既可以传文件对象, 也可以传普通的键值对
    • 内置对象传文件必须要指定两个参数
      • contentType: false
      • processData: false
    def test(request):
        print(request.POST)  # <QueryDict: {'username': ['bigb'], 'password': ['123']}>
        print(request.FILES)  # <MultiValueDict: {'upload_file': [<InMemoryUploadedFile: githublogo.jpg (image/jpeg)>]}
        return render(request, 'test.html')
    
    username:<input type="text" name="username">
    password:<input type="password" name="password">
    upload_file:<input type="file" name="upload_file" id="d2">
    <button id="d1">提交</button>
    
    
    <script>
        
        $('#d1').on('click', function () {
            // 1.先生成一个内置对象
            let MyFormData = new FormData
            // 2.添加普通键值数据
            MyFormData.append('username', 'bigb')
            MyFormData.append('password', '123')
            // 3.获取并添加文件对象
            MyFormData.append('upload_file', $('#d2')[0].files[0])
            $.ajax({
                url: '',
                type: 'post',
                data: MyFormData,
                // 发送文件必须要指定两个参数
                contentType: false,  // 不使用任何编码, MyFormData内部自带编码
                processData: false,  //不要处理数据
                success: function (data) {
                    alert(123)
                }
            })
        })
    </script>
    
    
    

    序列化模块

    • 后端数据(一般是字典或者列表套字典)序列化后发送给前端, 实现前后端分离
    • serialize()方法可以序列化queryset对象
      • 第一个参数: 'json'
      • 第二个参数: queryset对象
    from django.core.serializers
    
    # serialize()方法可以序列化queryset对象
    def test1(request):
        user_queryset = models.User.objects.all()
        # 第一个参数: 数据格式json, 第二个参数: queryset对象
        res = serializers.serialize('json', user_queryset)
        return HttpResponse(res)
    
    
    '''
    [{"model": "app01.user", "pk": 1, "fields": {"username": "alpha", "password": "111", "edu_level": 1}}, {"model": "app01.user", "pk": 2, "fields": {"username": "bravo", "password": "111", "edu_level": 2}}, {"model": "app01.user", "pk": 3, "fields": {"username": "charlie", "password": "111", "edu_level": 3}}, {"model": "app01.user", "pk": 4, "fields": {"username": "delta", "password": "111", "edu_level": 4}}, {"model": "app01.user", "pk": 5, "fields": {"username": "echo", "password": "111", "edu_level": 5}}]
    '''
    
  • 相关阅读:
    FineReport实现java报表报表展示的效果图
    Android开发最佳学习路线图
    void及void指针含义的深刻解析
    7个最好的免费杀毒软件下载
    linux-socket
    java实现第四届蓝桥杯逆波兰表达式
    java实现第四届蓝桥杯逆波兰表达式
    java实现第四届蓝桥杯逆波兰表达式
    java实现第四届蓝桥杯逆波兰表达式
    java实现第四届蓝桥杯有理数类
  • 原文地址:https://www.cnblogs.com/bigb/p/11966794.html
Copyright © 2011-2022 走看看