目录
orm查询优化
惰性查询, 目的: 减少不必要的数据库操作, 降低数据库的压力
缓存数据库, redis, mongodb, 目的: 缓解主库压力, 相当于一个非常大的内存, 速度快同时也能做持久化
能少走一次数据库就少走一次
only与defer
only:
- only括号内放字段, 查询结果是一个列表套数据对象
- "对象.括号内的字段"不会再查询数据库, 直接获取属性值
- "对象.括号内没有的字段"会查询数据库获取结果
res = models.Book.objects.only('title') print(res) # <QuerySet [<Book: 红楼梦>, <Book: 西游记>, ...]> for i in res: print(i.title) # 查1次数据库 print(i.price) # 查5次数据库
defer:
- defer与only互为反操作
- "对象.括号内的字段"会查询数据库获取结果
- "对象.括号内没有的字段"不会再查询数据库, 直接获取属性值
res = models.Book.objects.only('title') for i in res: print(i.title) # 查5次数据库 print(i.price) # 查1次数据库
selected_related与prefetch_related
selected_related:
- select_related括号内只能放外键字段,
- 并且外键字段只能是多对一或者一对一, 不能是多对多,
- 内部是自动联表操作, 会将括号中的外键字段所关联的表与当前表自动拼接成一张表,
- 然后将表中的一条条数据封装成一个个对象, 使跨表查询也不需要重复走数据库,
- 括号中可以放多个外键字段, 会将全部外键字段关联的表与当前表拼成一张大表
res = models.Book.objects.all() for i in res: print(i.publish) # 查询外键信息时, 需查询5次数据库 res = models.Book.objects.select_related('publish') for i in res: print(i.title) # 查1次数据库 print(i.publish) # 查1次数据库
prefetch_related:
- 内部是子查询, 按步骤查询多张表, 然后将查询的结果封装到对象中, 给用户的感觉像是联表操作
-
res = models.Book.objects.prefetch_related('publish', 'authors') for i in res: print(i.publish) # 查3次数据库 print(i.authors.all()) # 查3次数据库
小结
selected_related: 耗时在数据库层面的联表操作上
prefetch_related: 耗时在查询的次数上
当两张表特别大时, selected_related花费时间可能更多
MTV与MCV模型
django自称为MTV框架, 本质还是MVC
MTV:
- M: models
- T: templates
- V: views
MVC:
- M: models
- V: views
- C: controllar, 包含urls.py, 路由匹配
choices参数
性别, 学历等字段可能性都是能完全列举的,
存数字, 取的时候按照提前设定的对应关系取出真正的数据
migrations文件夹下必须要有一个__init__.py
文件, 否则会报错: No changes detected
''' class User(models.Model): ... gender_choice = ( (1, '男'), (2, '女'), (3, '其他'), ) gender = models.IntegerField(choices=gender_choice) from app01 import models user_obj1 = models.User.objects.get(pk=1) user_obj2 = models.User.objects.get(pk=4) print(user_obj1.get_gender_display()) # 男 print(user_obj2.get_gender_display()) # 4 如果存储的数字不在提前设定的对应关系中 能够正常存储, 也能够正常获取 choices字段类型获取对应关系值的句式: get_字段名_display() 弱限制, 没有对应关系时, 获取的结果为表中实际结果 对应关系中的第一个参数不一定是数字, 也可以是字符串 '''
ajax简介
XML
xml也是一门标记语言, 应用场景:
- 写配置文件
- 写前端页面
- 专门用来开发企业内部管理软件的框架: odoo
- odoo框架内部功能实现全部依赖于python2, 薪资功能的实现最复杂
AJAX
最大的优点是在不重新加载整个页面的情况下, 可以与服务器交换数据并更新部分网页内容
同步交互: 客户端发出一个请求后, 需要等待服务器响应结束后, 才能发出第二个请求
异步交互: 客户端发出一个请求后, 无需等待服务器响应结束后, 就能发出第二个请求
''' 1. 页面上有三个input框 2. 前两个框输入数字, 并将输入的数字用post请求提交到后端, 最后一个框展示两数之和 3. 要求页面不刷新 '''
''' 1. 页面上有三个input框 2. 前两个框输入数字, 并将输入的数字用post请求提交到后端, 最后一个框展示两数之和 3. 要求页面不刷新 def ajax(request): # print(request.is_ajax()) # 判断当前请求是否是ajax请求 # print(request.POST) # ajax发送的post请求, 普通的键值对也在request.POST中 if request.is_ajax(): d1 = request.POST.get('d1') d2 = request.POST.get('d2') res = int(d1) + int(d2) return HttpResponse(res) # 结果返回给异步回调函数, 一旦使用ajax请求, 数据只与回调函数交互 return render(request, 'ajax.html') <script> $('#d4').on( 'click', function () { // 开启ajax语法句式: $.ajax({ url: '', // 控制数据的后端地址, 和form表单中的action用法一样 type: 'post', // 控制数据提交方式, 不写默认是get请求 data: {'d1': $('#d1').val(), 'd2': $('#d2').val()}, // 提交的数据 success: function (data) { // data为异步提交数据后, 后端处理数据的返回结果 $('#d3').val(data) // 回调函数处理返回结果 } }) } ) </script> '''
前后端数据交互的编码格式
a标签的href参数: get请求
form表单: get/post请求, post请求无法发送json格式数据
ajax: get/post请求, post请求默认编码格式为urlencoded
get请求数据格式为单一格式: url?x=a&y=b
post请求的三种数据编码格式
- urlencoded, multipart/formdata, application/json
- 查看请求方式: f12-->Network-->Headers-->Request Headers-->Content-Type
- 查看请求原数据: ...-->Form Data-->view source
- django针对urlencoded数据, username=jason&password=123, 会自动解析并封装到request.POST中
- django针对multipart/formdata数据, 在浏览器中无法查看, 但是会将满足urlencoded的数据解析到request.POST中, 将文件对象解析到request.FILES中
- 发送json格式数据只能借助ajax
- 在涉及前后端交互时, 要做到数据的格式与编码的格式一致
''' <script> $('#d4').on( 'click', function () { $.ajax({ url: '', type: 'post', contentType: 'application/json', // post请求发送json数据需要的参数及参数值 data: JSON.stringify({'username': 'jason', 'password': '123'}), // 前端数据使用JSON.stringify序列化为json格式 success: function (data) { alert(data.username) } }) } ) </script> def ajax(request): from django.http import JsonResponse import json if request.is_ajax(): json_bin = request.body # 获取json格式二进制数据 json_str = json_bin.decode('utf8') # 解码 user_dic = json.loads(json_str) # 反序列化 return JsonResponse(user_dic) # JsonResponse会自动将后端的字典转换成前端的object类型数据 return render(request, 'ajax.html') '''
ajax发送文件格式数据
Ajax传文件需要借助js中的内置对象
js实例化对象的关键字: new
该对象既可以携带文件数据, 也支持普通的键值对
''' <script> $('#d1').on( 'click', function () { var myFormData = new FormData(); // 实例化得到myFormData对象 myFormData.append('username', 'jason'); // 添加普通键值数据 myFormData.append('myfile', $('#d2')[0].files[0]); // 获取input框中文件对象, 并添加到myFileData对象中 $.ajax({ ..., data: myFormData, contentType: false, // 不使用myFormData对象内部自带的编码, 类似于json.dumps自动转码中文 processData: false, // 设置浏览器不处理发送的数据 ... }) } ) </script> def ajax(request): if request.is_ajax(): print(request.POST) # <QueryDict: {'username': ['jason']}> print(request.FILES) # <MultiValueDict: {'myfile': [<...: 20天背完四级核心词汇.pdf ...>]}> ... '''
django内置的序列化模块
drf: django restframework
序列化的目的: 将数据整合成一个大字典的形式, 方便前后端分离之后数据的交互
def serialize(request): from django.core import serializers user_queryset = models.User.objects.all() res = serializers.serialize('json', user_queryset) # json为序列化的数据格式 return HttpResponse(res) # [{"model": "app01.user", "pk": 1, "fields": {"username": "jason", "password": 123, "gender": 1}}, ...]