Django篇--->七

Django查询

聚合查询
        关键字:aggregate
		from django.db.models import Max,Min,Count,Sum,Avg

	分组查询
        关键字:annotate
        1.最简单的规律
            models后面点什么 就是按什么分组  
        
	F与Q查询
        from django.db.modles import F,Q
        F  能够帮助你获取到表中字段所对应的数据
        # 书籍的库存数与卖出数
        models.Book.objects.filter(kucun__gt=F('maichu'))
        
        因为filter过滤的条件的都是and连接 
        modesls.Book.objects.filter(Q(title='python'),Q(price=666))
        modesls.Book.objects.filter(Q(title='python')|Q(price=666))
        modesls.Book.objects.filter(~Q(title='python')|Q(price=666))
        
        # Q进阶用法
        q = Q()
        q.connector = 'or'
        q.children.append(('title','python'))
        q.children.append(('title__icontains','python'))
        q.children.append(('price',666))
        models.Book.objects.filter(q)  # 默认还是and关系  
	
	django中如何开启事务
        from django.db import transaction
        try:
            with transaction.atomic():
                # 事务操作
        except BaseException as e:
            print(e)  
	
    
  
    
	常见字段及参数
        AutoField()
        DateField()
        DateTimeField()
            auto_now
            auto_now_add
        TextField()
        EmailField()          varchar(...)
        BooleanField()        传布尔值  存0/1
        
         
	
	自定义char字段
        class MyCharField(models.Field):
            
            
            def db_type(self,connection):
                return 'char(%s)'%self.max_length
            
	
	orm查询优化
        only
        defer
        
        
        select_related
        prefetch_related
        
	图书管理系统
		书籍的增删改查

模型表的choice参数
比如选择性别‘男女’,往数据库中填写的数字是0,1

模型层

class Userinfo(models.Model):
    username = models.CharField(max_length=32)
    password = models.IntegerField()

    # 定义 choice 参数
    choices = (
        (1, 'male'),
        (2, 'female'),
        (3, 'others')
    )
    gender = models.IntegerField(choices=choices)

    '''
    定义choice参数时,括号内放的对应关系是一个个元组,如果我存入的数字不在我模型层
    定义的choice参数内(注意:虽然存入的数字没有对应关系,但是是可以存的)
    '''

视图层

from app01 import models

    res = models.Userinfo.objects.filter(pk=1).first()
    ret = models.Userinfo.objects.filter(pk=4).first()
    print(res.username) #jason
    print(res.gender) # 1
    # 正确方式
    print(res.get_gender_display()) # male

    print(ret.username) # nick
    print(ret.gender)# 3
    # 正确方式
    print(ret.get_gender_display()) # others
    
    res = models.Userinfo.objects.filter(pk=5).first()
    print(res.get_gender_display()) # 4  数字4没有在choice参数内设置对应值,所以取出的											 任然是数字
    '''
    如上所示,针对choices字段,如果你想要获取数字对应的值,不能直接点字段取值
    固定的书写方式为:数据对象.get_字段名_display(),当需要取值的数字不在choice参数内所设置的对应关系,那么取值获取到的还是数字
    '''

choice参数使用模版

record_choices = (('checked', "已签到"),
                      ('vacate', "请假"),
                      ('late', "迟到"),
                      ('noshow', "缺勤"),
                      ('leave_early', "早退"),
                      )
        record = models.CharField("上课纪录", choices=record_choices, 												default="checked",) 
    
    
        
        
        score_choices = ((100, 'A+'),
                     (90, 'A'),
                     (85, 'B+'),
                     (80, 'B'),
                     (70, 'B-'),
                     (60, 'C+'),
                     (50, 'C'),
                     (40, 'C-'),
                     (0, ' D'),
                     (-1, 'N/A'),
                     (-100, 'COPY'),
                     (-1000, 'FAIL'),
                     )
        score = models.IntegerField("本节成绩", choices=score_choices, 												default=-1)
    

MTV与MVC模型

django号称是MTV框架,其实它还是MVC框架
	MTV:
		M: models
		T: templates
        V: views
    MVC:
        M: modles
		V: views
		C: controller(路由匹配)

Ajax(*****)

什么是Ajax: AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)

AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。

​ 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;(等待期间不做任何事)

​ 异步交互:客户度发出一个请求后,不需要等待服务器响应结束,可直接发出第二个请求。(直接执行下一行代码)

​ 阻塞与非阻塞:表示的是程序的执行状态

Ajax优点

  • AJAX使用JavaScript技术向服务器发送异步请求;
  • AJAX请求无须刷新整个页面;
  • 因为服务器响应内容不再是整个页面,而是页面中的部分内容,所以AJAX性能高;

两个关键点:1.局部刷新:一个页面,不是整体刷新,而是页面的某个地方局部刷新
2.异步提交

基于jQuery实现的Ajax

ajax基本语法

//在 html script中使用
$.ajax({
    url: '/index/',  //提交的数据路径,不写默认是当前路径
    type: 'post',   //标定ajax的请求方式
    data:{'name':'jason', 'age': 18},  //data后面跟的是你提交给后端的数据
    //success 为回调函数
    success:function(data){    //data是后端返回的数据
        alert(data)
    }
    
})

1.展示一个前端页面,页面上有三个输入框,前面两个框输入数字,点击按钮朝后端发送请求,页面在不刷新的情况下,完成数字的加法运算

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script>

</head>
<body>

<input type="text" id="t1">+<input type="text" id="t2">=<input type="text" id="t3">
<p>
    <button class='btn btn-primary' id="b1">计算</button>
</p>

<script>
    //绑定事件
    $('#b1').on('click',function(){
        //ajax写法
        $.ajax({
            url: '/index/',
            type: 'post', //设置发送方式是post请求
            //获取两个输入框的值
            data:{'t1':$('#t1').val(), 't2':$('#t2').val()},//data是提交给后端的数据
            //success回调函数
            success:function(data){   //data是后端返回的数据
                $('#t3').val(data)
            }
        })
    })
</script>
</body>
</html>

views.py

def index(request):
    if request.is_ajax():
        if request.method == 'POST':
            t1 = request.POST.get('t1') # 后端获取到前端的数据都是字符串形式
            t2 = request.POST.get('t2') # 后端获取到前端的数据都是字符串形式
            res = int(t1) + int(t2)  # 转换成 int类型
            return HttpResponse(res)

    return render(request, 'index.html')

Ajax传 json 格式数据
django后端针对json格式的数据,不会自动帮你解析,会原封不动的存放在 request.body 中,
可以手动处理,获取数据

json_bytes = request.body
json.str = str(json_bytes,encoding='utf8')
json_dict = json.loads(json.str)

注意点:在前端html 中必须:
	1.指定contentType参数
    	contentType: 'application/json'
    2.要将你发送的数据,确保是json格式的
    	data:JSON.stringify({'username': 'jason', 'password': '123'})

js.html.py

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>

</head>
<body>
<input type="text" name="name" id="d1">
<input type="password" name="password" id="d2">
<button id="d3">ajax提交json格式数据</button>
</body>
<script>
  $('#d3').click(function () {
      var pos_data = {'name':$('#d1').val(),'password':$('#d2').val()};  //获取input框数据
      //JSON.stringify相当于json.dumps(),转化成json格式的字符串
      var pos = JSON.stringify(pos_data);  //转换格式

      $.ajax({
          url:'',
          type:'post',
          data:pos,  //发送的数据
          contentType:'application/json',  //告诉后端你这次的数据是json格式
      dataType:'json',
          success:function (data) {
              alert(data)
          }

      })
  })
</script>
</html>

视图层

def js(request):
    if request.method == 'POST':
        json_bytes = request.body
        # 后端 需要手动去request.body中获取json格式数据
        print(request.body) # b'{"name":"tank","password":"123"}'
        import json
        bytes_str = request.body.decode('utf-8')
        print(json.loads(bytes_str)) # {'name': 'tank', 'password': '123'}
    return render(request, 'js.html')

form表单和Ajax传文件

1.contentType前后端传输数据编码格式

前后端传输数据编码格式

  • urlencoded
  • formdata
  • json

2.form表单和ajax上传文件区别

form表单

1.默认使用的编码格式是urlencoded
数据格式:name = jason&pwd=123
django后端针对urlencoded编码格式的数据会自动解析并放在request.POST中供用户获取。

2.可以修改formdata传文件
django后端针对formdata编码格式的数据会自动解析并放在request.FILES中供用户获取。

​ 需要利用内置对象 Formdata,该对象即可以传普通键值,也可以传文件

模型层

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>

</head>
<body>
<form action="" enctype="multipart/form-data" method="post">
  <input type="text" name="username" id="t1">
  <input type="password" name="password" id="t2">
  <input type="file" name="myfile" id="myfile">
 <input type='submit' value = 'form表单上传文件'>    //form表单上传文件格式
  
</form>
<button id="b1">提交</button>   //ajax上传文件格式,触发下面的ajax
<script>
	//绑定提交按钮
    $('#b1').click(function() {
        //1.先生成一个Formdata对象
        var myFormdata = new FormData();
        //2.朝对象中添加普通键值
        myFormdata.append('username', $('#ti').val());  //既可以上传普通键值
        myFormdata.append('password', $('#t2').val());
        //3.朝对象中添加文件数据,分三步
            //1.先通过jQuery获取查到到标签
            //2.将jQuery对象转换成原生的js 对象
            //3.利用原生js对象的方法,直接获取文件内容
        myFormdata.append('myfile', $('#t3')[0].files[0]); //也可以上传文件

        $.ajax({
            url: '',
            type: 'post',
            data:myFormdata,  //直接丢对象
            // ajax传文件,一定要指定两个关键性的参数
            contentType: false,  //不用任何编码,因为Formdata对象自带编码,django能够识别该对象
            processData: false, //告诉浏览器不要处理我的数据,直接发就行
            success:function(data){    //后端返回给客户端数据
                alert(data)
            }
        })
    })
</script>
</body>
</html>

视图层

#forms表单上传文件
def home(request):
    if request.method == 'GET':  //渲染页面
        return render(request,'home.html')
    #获取文件信息
    myfile = request.FILES.get('myfile')  //获取form表单上传的文件
    print(myfile)    //上传文件名
    return HttpResponse('ok')

#ajax上传文件
def upload(request):
    if request.is_ajax:
        if request.method == 'POST':
            print(request.POST)  # <QueryDict: {'username': ['undefined'], 'password': ['111']}>
            print(request.FILES) # <MultiValueDict: {'myfile': [<InMemoryUploadedFile: 考试内容.txt (text/plain)>]}>
            return HttpResponse('后端已收到')
    return render(request, 'upload.html')
'''注意事项:ajax传文件需要注意的事项
		1.利用formdata对象,能够简单的快速传输数据(普通键值 + 文件)
		2.有几个参数
				data:formdata  直接丢对象
				contentType: false
				processData: false

'''
'''1.form表单上传文件需要指定编码格式enctype = 'multipart/form-data'。ajax也需要设置一样的编码格式,然后需要创建一个Formdata对象
获取file文件的内容都是通过request.FILES.get()'''

总结:

1.如果不是上传文件,form表单input的话,就直接传了,contentType默认是urlencoded编码方式
2.如果是上传文件,ajax上传文件就是先创建一个Formdata对象,通过append,把key,value参数传进去。注意:form表单和ajax上传的文件都是通过request.FILES.get()获取。
3.ajax提交json格式的数据,先创造出一个对象,把数据放在对象里面,然后转换成json格式的字符串,通过JSON.stringify(data),这里的contentType必须设置为'application/json',这样它的数据在视图中就能通过request.body获取到,是二进制格式,需要转换成字符串。
4、在前端接收到后台json格式数据,可以在ajax那里写dataType:'json',它会自动转换成对象

contentType前后端传输数据编码格式**

contentType前后端传输数据编码格式
    
        form表单 默认的提交数据的编码格式是urlencoded
            urlencoded
                username=admin&password=123这种就是符合urlencoded数据格式
                
                django后端针对username=admin&password=123的urlencoded数据格式会自动解析
                将结果打包给request.POST 用户只需要从request.POST即可获取对应信息
               
            formdata
                django后端针对formdata格式类型数据 也会自动解析
                但是不会方法request.POST中而是给你放到了request.FILES中
            
        ajax  ajax默认的提交数据的编码格式也是urlencoded
            username=jason&password=123
            
        总结:django后端针对不同的编码格式数据 会有不同的处理机制以及不同的获取该数据的方法
    
    """
    前后端在做数据交互的时候 一定一定要表明你所发的的数据到底是什么格式
    
    前段后交互 你不能骗人家
    你的数据时什么格式 你就应该准确无误告诉别人是什么格式   

序列化组件

视图层

from app01 import models
from django.core import serializers
def ser(request):
    user_queryset = models.Userinfo.objects.all()
    #方式一# 自行封装成列表套字典
    # user_list = []  # 自行封装成列表套字典
    # for user_obj in user_queryset:
    #     user_list.append(
    #         {'username': user_obj.username,
    #          'password': user_obj.password,
    #          'gender': user_obj.get_gender_display}
    #     )

    # 方式二-用模块处理
    res = serializers.serialize('json', user_queryset)
    print(res)
	return render(request, 'ser.html', locals())

模板层

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>

<p>{{ res }}</p> # 模块处理,直接将所有信息封装到一个个字典中,方式二
    #以下对应的是方式一
{#<p>{{ user_list }}</p>   #列表里面套字典#}
{#{% for foo in user_list %}#}
{#    <p>{{ foo.username }}</p>#}
{#    <p>{{ foo.password }}</p>#}
{#    <p>{{ foo.gender }}</p>   # 字典取值#}

{#{% endfor %}#}

</body>
</html>

ajax + sweetalert

模型层

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script>
    {% load static %}
    <link rel="stylesheet" href="{% static 'dist/sweetalert.css' %}">
    <script src="{% static 'dist/sweetalert.min.js' %}"></script>
    <style>
        div.sweet-alert h2 {
            padding-top: 10px;
        }
    </style>
</head>
<body>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <h2>数据展示</h2>
            <table class="table table-hover table-striped table-bordered">
                <thead>
                    <tr>
                        <th>序号</th>
                        <th>用户名</th>
                        <th>密码</th>
                        <th>性别</th>
                        <th>操作</th>
                    </tr>
                </thead>
                <tbody>
                    {% for user_obj in user_queryset %}
                        <tr>
                            <td>{{ forloop.counter }}</td>
                            <td>{{ user_obj.username }}</td>
                            <td>{{ user_obj.password }}</td>
                            <td>{{ user_obj.get_gender_display }}</td>
                            <td>
                                <a href="#" class="btn btn-primary btn-sm">编辑</a>
                                <a href="#" class="btn btn-danger btn-sm cancel" delete_id="{{ user_obj.pk }}">删除</a>
                            </td>
                        </tr>
                    {% endfor %}
                </tbody>


            </table>
        </div>
    </div>
</div>


<script>
    $('.cancel').click(function () {
        var $btn = $(this);
        swal({
          title: "你确定要删吗?",
          text: "你要是删了,你就准备好跑路吧!",
          type: "warning",
          showCancelButton: true,
          confirmButtonClass: "btn-danger",
          confirmButtonText: "对,老子就要删!",
          cancelButtonText: "算了,算了!",
          closeOnConfirm: false,
            showLoaderOnConfirm: true
        },
        function(){
            $.ajax({
                url:'',
                type:'post',
                data:{'delete_id':$btn.attr('delete_id')},
                success:function (data) {
                    if (data.code==1000){
                        swal(data.msg, "你可以回去收拾行李跑路了.", "success");
                        // 1.直接刷新页面
                        {#window.location.reload()#}
                        // 2.通过DOM操作 实时删除
                        $btn.parent().parent().remove()
                    }else{
                        swal("发生了未知错误!", "我也不知道哪里错了.", "info");
                    }
                }
            });

        });
    })
</script>


</body>
</html>

视图层

"""
当你是用ajax做前后端 交互的时候 
你可以考虑返回给前端一个大字典
"""
import time
from django.http import JsonResponse
def sweetajax(request):
    if request.method == 'POST':
        back_dic = {"code":1000,'msg':''}
        delete_id = request.POST.get('delete_id')
        models.Userinfo.objects.filter(pk=delete_id).delete()
        back_dic['msg'] = '后端传来的:真的被我删了'
        time.sleep(3)
        return JsonResponse(back_dic)
    user_queryset = models.Userinfo.objects.all()
    return render(request,'sa.html',locals())
原文地址:https://www.cnblogs.com/chmily/p/11757036.html