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}}]
'''

Django 07的更多相关文章

  1. Django 07 Django模型基础2 (常用查询和多表关联)

    Django 07 Django模型基础2 (常用查询和多表关联) 一.常用查询 #查找数据 def search_user(request): #获取 rs = User.objects.first ...

  2. day64 Pyhton 框架Django 07

    day67 内容回顾 视图 1. CBV 定义 from django.views import View class Addpub(View): def get(self,request): sel ...

  3. 07: Django 使用ldap登录、注销等

    目录:Django其他篇 01:Django基础篇 02:Django进阶篇 03:Django数据库操作--->Model 04: Form 验证用户数据 & 生成html 05:Mo ...

  4. Django框架07 /cookie和session

    Django框架07 /cookie和session 目录 Django框架07 /cookie和session 1. django请求生命周期 2. cookie 3. session 4. 总结 ...

  5. Django REST Framework API Guide 07

    本节大纲 1.Permissions 2.Throttling Permissions 权限是用来授权或者拒绝用户访问API的不同部分的不同的类的.基础的权限划分 1.IsAuthenticated ...

  6. Django 2.0 学习(07):Django 视图(进阶-续)

    接Django 2.0 学习(06):Django 视图(进阶),我们将聚焦在使用简单的表单进行处理和精简代码. 编写简单表单 我们将用下面的代码,来替换之前的detail模板("polls ...

  7. 07 - Django应用第四步

    知识点 1) 表单的编写 CSRF问题 forloop.counter 2) 视图函数的知识 GET和POST HttpResponseRedirect的使用 reverse的使用 3) 通用视图 C ...

  8. 07 Django组件-中间件

    中间件 方式一:函数式:中间件[middleware],也叫钩子方法[钩子函数],hook Django中的中间件是一个轻量级.底层的插件系统,可以介入Django的请求和响应处理过程,修改Djang ...

  9. 07.Django学习之model进阶

    一 QuerySet 可切片 使用Python 的切片语法来限制查询集记录的数目 .它等同于SQL 的LIMIT 和OFFSET 子句. >>> Entry.objects.all( ...

随机推荐

  1. mpvue开发微信小程序,分享按钮报错:`Cannot read property 'apply' of null`

    用mpvue开发微信小程序,分享按钮报错:Cannot read property 'apply' of null onShareAppMessage 是于微信小程序Pages的生命周期钩子,顾这个方 ...

  2. 航空概论(历年资料,引之百度文库,PS:未调格式,有点乱)

    航空航天尔雅 选择题1. 已经实现了<天方夜谭>中的飞毯设想.—— A——美国2. 地球到月球大约—— C 38 万公里3. 建立了航空史上第一条定期空中路线—— B——德国4. 对于孔明 ...

  3. Vue2.x与bootsrap-table动态添加元素和绑定事件无效

    一.问题:     最近在使用vue与bootstrap-table结合生成表格时,按以前的经验----每列数据可用formatter:function(value,row,index){}进行一些其 ...

  4. python容器类型元组的操作

    元组:使用小括号进行表示一组元素,其元素与元素之间使用逗号隔开:注意:元组的的值是不可修改的: 1.元组值得增加:元组是不可以直接增加值的,但是可以通过+进行拼接 # 声明一个元组: tuple1 = ...

  5. 【Oracle】Oracle数据库基本指标查看

    目录 1.查看表空间 2.查看用户 3.查看数据库内存 4.查看数据库版本 5.oracle归档情况 6.查看redo log日志位置 7.查看数据库的控制文件 8.查看RMAN的备份情况 9.FRA ...

  6. ArcGIS 用QueryTask查询上限1000的问题

    1.打开ArcGIS Server找到自己发布的服务,右键Service Properties,左侧点击Parameters,右侧有一个Maximum number of records return ...

  7. 详解在Linux系统中安装JDK

    本文以在CentOS 7.6中安装JDK8为例进行安装,其他系统和版本都是大同小异的. 下载 进入Oracle官方网站的下载页面. 首先,接受许可协议,如下图: 然后,根据Linux系统的位数选择要下 ...

  8. 设计模式之美学习(九):业务开发常用的基于贫血模型的MVC架构违背OOP吗?

    我们都知道,很多业务系统都是基于 MVC 三层架构来开发的.实际上,更确切点讲,这是一种基于贫血模型的 MVC 三层架构开发模式. 虽然这种开发模式已经成为标准的 Web 项目的开发模式,但它却违反了 ...

  9. pwnable.kr 第一天

    1.FD 直接通过ssh连接上去,然后,看下源代码. #include <stdio.h> #include <stdlib.h> #include <string.h& ...

  10. selenium常用命令之页面元素定位

    WebDriver driver= new ChromeDriver();   <input type="text" id="phone" name=&q ...