ORM优化、事务、字段及Ajax

ORM查询优化

1.ORM的查询默认都是惰性处理
惰性处理:如果只是书写了orm语句,在后面根本没有用到该语句所查询出来的参数,那么orm会自动识别出来,直接不执行。
举例:res=models.Book.objects.all() # 这时orm是不会走数据库的
	print(res) # 只有当要用到上述orm语句的结果时,才去数据库查询
2.ORM的查询自带分页处理

3.only与defer
res=models.Book.objects.only('title','price')
    #print(res) # queryset [数据对象、数据对象]
    for obj in res:
        print(obj.title)  #点击括号内填写的字段 不走SQL查询
        print(obj.price)
        print(obj.publish_time) # 可以点击括号内没有的字段获取数据 但是会走SQL查询
only会把括号内字段对应的值封装到查询返回的对象中,通过对象点括号字段,不需要再走数据库查询,直接返回结果,一定点了不是括号内的字段,就会去走数据库查询
'''
only英语的意思就是只有,我们可以理解为通过only查询出来的对象内只会有小括号内的字段的值,如果想要获取其它字段的值,还得在查一次数据库或者说在执行一次SQL语句
'''

res = models.Book.objects.defer('title','price')
    # print(res)  # queryset [数据对象、数据对象]
    for obj in res:
        # print(obj.title) # 点击括号内填写的字段 走SQL查询
        # print(obj.price)
        print(obj.publish_time)  # 点击括号内没有的字段获取数据 不走SQL查询
'''
	defer刚好和only相反,defer小括号里写了啥,它反倒不给你,它会给你除了括号内的所有字段值。当你获取小括号内的字段值时,回去查询,获取不在小括号内的字段值时反倒不用去查询
'''

    res = models.Book.objects.all()
    for obj in res:
        print(obj.publish.name)  # 每次查询都走SQL
    res = models.Book.objects.select_related('publish') # 先连表后查询封装
    for obj in res:
        print(obj.publish.name)  # 不再走SQL查询
    res1 = models.Author.objects.select_related('author_detail') #括号内不支持多对多字段,其它一对多和一对一支持
    print(res1)

select_related括号内放外键字段,并且外键字段的类型只能是一对一和一对多,不能是多对多
内部自动做联表操作,会将括号内外键字段所关联的表与当前表自动拼接成一张表,然后将表中的数据一个个查询出来封装成一个个的对象,这样做就不会重复走数据库,减轻数据库压力。
select_related括号内可以放多个外键字段,用逗号隔开,会将多个外键字段关联的表拼接成一张大表
后续对象通过正反向查询跨表,内部不会走数据库查询

	res = models.Book.objects.prefetch_related('publish')  # 子查询
    for obj in res:
        print(obj.publish.name)
prefetch_related内部是子查询,会自动按照步骤查询多张表,然后将查询的结果封装到对象中,这样给用户的感觉还是链表操作。
括号内支持多个外键字段,并且没有类型限制,每放一个外键字段,就会多走一条SQL语句,多查询一次表。
'''
将多次查询之后的结果封装到数据对象中,后续对象通过正反向查询跨表,内部不会再走数据库查询
'''

ORM事务操作

django orm提供了至少三种开启事务的方式
方式1:settings.py配置文件数据库相关添加键值对  全局有效
"ATOMIC_REQUESTS": True每次请求所涉及到的orm操作同属于一个事务

方式2:装饰器   视图函数的局部有效
from django.db import transaction
@transaction.atomic
def index():pass

方式3with上下文管理(视图函数里面的with上下文里面的才有效)
from django.db import transaction
def reg():
	with transaction.atomic():
		pass

ORM常用字段类型

AutoField
int自增列,必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列.

CharField
字符类型,必须提供max_length参数, max_length表示字符长度.

IntegerField 整数

DecimalField(max_digits=None, decimal_places=None):可以指定精度的十进制浮点数
参数max_digits表示总位数
参数decimal_places表示小数位数

DateField[auto_now=False, auto_now_add=False]):日期
参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为false
参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为false,不人为修改不会改变
参数auto_now_add和auto_now是相互排斥的,组合将会发生错误

DateTimeField[auto_now=False, auto_now_add=False]):日期
参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为false
参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为false,不人为修改不会改变
参数auto_now_add和auto_now是相互排斥的,组合将会发生错误

BooleanField
传布尔值自动存01

TextField
存储大段文本

EmailField
存储邮箱格式数据

FileField
传文件对象 自动保存到提前配置好的路径下并存储该路径信息

ORM还支持用户自定义字段类型
	class MyCharField(models.Field):
        def __init__(self, max_length, *args, **kwargs):
            self.max_length = max_length
            super().__init__(max_length=max_length, *args, **kwargs)

        def db_type(self, connection):
            return 'char(%s)' % self.max_length


    class User(models.Model):
        name = models.CharField(max_length=32)
        info = MyCharField(max_length=64)

ORM常用字段参数

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其实质是利用浏览器提供的一个特殊的对象(XMLHttpRequest)异步地向服务器发送请求,服务器返回部分数据,浏览器让你去利用这些数据对象页面做部分的更新,整个过程,页面无刷新,不打断用户的操作。

同步和异步的区别
	同步:如果与服务器端的交互方式是同步,当客户端与服务器交互时,客户端就不能进行其他操作,只能等待服务器端的响应,会刷新页面。
	异步:当客户端正在进行正常操作时,还可以同时与服务器进行交互,服务器响应客户端信息,将信息更新到网页局部,整个过程页面不刷新。
'''
ajax不是一种新语言。它是几种技术的综合使用。
ajax是一种技术。
ajax是一种在WEB应用程序中向服务器发送异步请求,接收异步响应的技术。 
特点:异步提交 局部刷新
我们所学习的是jQuery封装的版本 所以页面上必须要提前导入jQuery资源
'''

基本语法:
$.ajax({
    url:'',   //后端地址 三种填写方式,与form标签的action一致(当前页面,完整URL,指定URL路径)
    type:'post',  //请求方式,默认是get
    data:{'v1':v1Val,'v2':v2Val},  //发送的数据
    success:function (args) {  //后端返回结果之后自动触发 args接收后端返回的数据
        $('#d3').val(args)
                            }   
    })

ajax小案例

urls.py:
#ajax小案例
path('ab_ajax/',views.ajax_func,name='ajax_view'),

views.py:
def ajax_func(request):
    if request.method == 'POST':
        v1=request.POST.get('v1')
        v2=request.POST.get('v2')
        v3=int(v1)+int(v2)
        return HttpResponse(v3)
    return render(request,'ajaxPage.html')

ajaxPage.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
</head>
<body>
<input type="text" id="d1">+<input type="text" id="d2"> =<input type="text" id="d3">
<button id="suBtn">点我发送ajax请求</button>
<script>
    //2.给按钮发送点击事件
    $('#suBtn').click(function (){
        //1.先获取两个框里的数据
        let v1val=$('#d1').val();
        let v2val=$('#d2').val();
        //3.发送ajax请求
        $.ajax({
            url:'',  //后端地址,不写给当前页面发送
            type:'post',  //请求方式,默认是get
            data:{'v1':v1val,'v2':v2val},  //发送数据
            success:function (args){  //后端返回结果之后自动触发 args接收后端返回的数据
               $('#d3').val(args)
            }
        })
    })
</script>
</body>
</html>

image

Content-Type

1.urlencoded
	ajax默认的编码格式、form表单默认也是
	数据格式  xxx=yyy&uuu=ooo&aaa=kkk
        request.POST\request.GET
	django后端会自动处理到request.POST中

2.formdata
	django后端针对普通的键值对还是处理到request.POST中,但是针对文件会处理到request.FILES中

3.application/json
ps:表单不支持 ajax可以
urls.py:
#ajax小案例
path('ab_ajax/',views.ajax_func,name='ajax_view'),

views.py:
def ajax_func(request):
    if request.method == 'POST':
       print(request.body)  # b'{"name":"jason","age":23}'
       import json
       res = json.loads(request.body)
       print(res,type(res)) # {'name': 'jason', 'age': 23} <class 'dict'>
       request.JSON = res
       print(request.JSON) #
    return render(request,'ajaxPage.html')

ajaxPage.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
</head>
<body>
<button id="btn">点击发送json数据</button>
<script>
    $('#btn').click(function (){
        $.ajax({
            url:'',
            type:'post',
            data:JSON.stringify({'name':'jason','age':23}), //js的json反序列化(把数据转换成json)
            contentType:'application/json',
            success:function (args){
                alert(args)
            }
        })
    })
</script>

</body>
</html>

ajax携带文件数据

<input type="file" id="d2">
<button id="d3">携带文件数据</button>
<script>
    $('#d3').click(function (){
        //1.先产生一个FormData对象
        let myFormDataObj = new FormData();
        //2.往该对象中添加普通数据
        myFormDataObj.append('name','jason');
        myFormDataObj.append('age',18);
        //3.往该对象中添加文件数据
        myFormDataObj.append('file',$('#d2')[0].files[0])
        //4.发送ajax请求
        $.ajax({
            url:'',
            type:'post',
            data:myFormDataObj,
            // ajax发送文件固定的两个位置
            contentType:false,
            processData: false,
            success:function (args){
                alert(args)
            }
        })
    })
</script>

后端:
def ajax_func(request):
    if request.method == 'POST':
        print(request.FILES)
        #<MultiValueDict: {'file': [<InMemoryUploadedFile: locale.hpi (application/octet-stream)>]}>
        print(request.POST)
        #<QueryDict: {'name': ['jason'], 'age': ['18']}>
    return render(request,'ajaxPage.html')

ajax补充说明

主要是针对回调函数args接收到的响应数据
1.后端request.is_ajax() 
	用于判断当前请求是否由ajax发出
2.后端返回的三板斧都会被args接收不再影响整个浏览器页面
3.选择使用ajax做前后端交互的时候 后端一般返回的都是字典数据
4.ajax自动反序列化后端的json格式的bytes类型数据
	dataType:'json'

代码:

urls.py:
# ajax回调函数相关问题
path('ab_ajax/',views.ab_ajax_func)
views.py:
def ab_ajax_func(request):
    if request.method == 'POST':
        data = {'code':10000,'username':'jason','age':18}
        #方式一
        import json
        user_data = json.dumps(data)
        return HttpResponse(user_data)
        # from django.http import JsonResponse
        # return JsonResponse(data)
    return render(request,'AjaxPage.html')

AjaxPage.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
</head>
<body>
    <button id="d1">发送ajax请求</button>

    <script>
        $('#d1').click(function (){
            $.ajax({
                url:'',
                type:'post',
                data:{'name':'jason'},
                dataType:'json',
                success:function (args){
                    console.log(args);
                    console.log(typeof args)
                    console.log(args.username)
                    {#let userObj = JSON.parse(args);#}
                    {#console.log(userObj);#}
                    {#console.log(typeof userObj);#}
                    {#console.log(userObj.username)#}
                }
            })
        })
    </script>
</body>
</html>

posted @   悠悠-winter  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示