一。choice字段。

  在django的orm中,创建如同性别,民。族等可选择的字段时,可以选择使用choice字段进行定义。

  这样的定义可以使用简单的数字代替数据量大的字符,减少数据库的负担。

  choice字段没有具体的关键字,而是在某个字段中设置choices值。

class User(models.Model):
    username = models.CharField(max_length=32)
    age = models.IntegerField()
    choices = (
        (1,'男'),(2,'女'),(3,'其他')
    )
    gender = models.IntegerField(choices=choices)

  choice是元组套元组的形式,前面的是输入的值和数据库中存储的值,后面的是获取时需要转换的值。

  存choice里面罗列的数字与中文对应使用user_obj.get_gender_display()方法,

  只要是choices字段 在获取数字对应的注释 固定语法  get_choices字段名_display()

  存没有罗列迟来的数字不会报错 还是展示数字。

二。MTV和MVC模式。

  在django中,是MTV框架。

  1.M:models 模型

  2.T:templates  模板

  3.V:view  视图

  而再其他框架中,也被称之为MVC,也就是:

  1.M:models 模型

  2.V:view  视图

  3.C:controller 控制器

三。ajax

  AJAX就是Asynchronous Javascript And XML)翻译成中文就是异步的JavascriptXML”

  也就是说ajax的特点是‘异步提交,局部刷新’,是一个强大的功能。  

  请求方式可以使用get方式,也可以使用post方法。

  除了ajax之外,以下方式也可以使用get和post方法。

  1.a标签href, 是get请求。

  2.浏览器输入url,get请求。

  3.form表单,  可以使用get和post。

  AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。

  这一特点给用户的感受是在不知不觉中完成请求和响应过程。

  小例子:

        $('#b1').on('click',function () {
            {#alert(123)#}
            // 点击按钮 朝后端发送post请求
            $.ajax({
                url:'',  // 控制发送给谁 不写就是朝当前地址提交
                type:'post',  // 发送方式是post请求
                data:{'i1':$('#i1').val(),'i2':$('#i2').val()},  // 发送的数据
                success:function (data) {  // data形参用来接收异步提交的结果
                    {#alert(data)#}
                    // 将后端计算好的结果 通过DOM操作 渲染到第三个input矿中
                    $('#i3').val(data)
                }
            })
        })

模板层

def test(request):
    if request.is_ajax():
        if request.method == 'POST':
            d1 = request.POST.get('d1')
            d2 = request.POST.get('d2')
            ret = int(d1)+int(d2)
            return HttpResponse(ret)
    return render(request,'test.html')

视图层

四。contentType前后端传输数据编码的格式。

   前后端传输数据编码格式有:

  1.urlencoded

  2.formdata

  3.json

  1.form表单

  在表单中,使用的编码格式默认是urlencoded

  数据的格式就是使用&符风格:name=lzx&pwd=123

    (1)而,django后端针对urlencoded编码格式的数据会自动解析并放到request.POST中供用户获取。(post格式)

    (2)在form中可以修改参数enctype,如果设置成multipart/form-data”,就可以接受文件格式的数据。在这个设定下,原来符合urlencoded编码格式的数据也会被服务端自动解析放入request.POST中。而如果是文件格式的数据,就会放入request.FILES中。

    如果没有设置multipart/form-data”,则会将该文件的文件名放入post中。

  2.ajax提交数据。

  在ajax中,提交数据的默认方式也是urlencoded,如果指定其中的参数contentType指定了什么类型的数据,客户端就会接受什么数据。

  如果数据格式不对,那么服务端就不会处理该数据。

  使用ajax发送json数据时,既不会放到POST中也不会放到FILES中,会原封不动的放入request.body中,这种数据就是普通的二进制加被json后的数据。

  (contentType:‘application/json’,,设置发送json格式数据)

  ajax格式:

$('#b1').on('click',function () {
    $.ajax({
        url:'',  // 控制发送给谁 不写就是朝当前地址提交
        type:'post',  // 发送方式是post请求
        data:JSON.stringify(
{'username':'jason','password':123}
),  // 发送的数据
        contentType:'application/json',  
        // 告诉后端你这次的数据是json格式
        success:function (data) {  
        // data形参用来接收异步提交的结果,操作数据
        }
})                            

  3.ajax格式传文件。

  在form表单中传输文件,只需要设置entype即可将文件添加到POST中。而ajax格式传输文件到POST需要使用一个对象:formData。

$('#b1').on('click',function () {
    // ajax传输文件 建议使用内置对象formdata
    var formData = new FormData();  // 既可以传普通的键值对 也可以传文件
    // 添加普通键值
    formData.append('username','jason');
    formData.append('password','123');
    // 传文件
    // 如何获取文件标签所存储的文件对象?  固定语法
    // 1.先用jQery查找到存储文件的input标签
    // 2.将jQuery对象转成原生js对象
    // 3.利用原生js对象的方法 .files[0]获取到标签内部存储的文件对象
    // 4.一定要指定两个参数都为false
    formData.append('my_file',$('#d1')[0].files[0]);
    $.ajax({
        url:'',  // 控制发送给谁 不写就是朝当前地址提交
        type:'post',  // 发送方式是post请求
        data:formData, // 发送的数据
        // ajax发送文件需要指定两个额外的参数
        processData:false,  // 告诉前端不要处理数据
        contentType:false,  // 不适用任何编码  
因为formdata对象自身自带编码 django后端也能够识别formdata对象 success:function (data) {
// data形参用来接收异步提交的结果 } }) })

  其中需要注意的是:

  1,formDate对象相当于一个字典,需要想其中append,键值对。而且及支持传输普通数据,又支持传输文件,而且有自带的编码。

  2,如何获取input中的文件

    1.先使用jquery语句获得$对象,在使用【0】获取原生js对象。最后使用.files【0】取出其中的文件对象。

  3.由于formdate对象自带编码格式,所以需要通过代码将编码格式取消:

    contentType:false

    processData:false

五。序列化组件。

  在前后端交互的过程中,django使用对象的方式即可处理数据,也就是对象点属性的方法。而这种对象其他语言识别不了,所以需要将其转化成一种可以让大家都能识别的语言,就需要使用到json格式。

  我们可以手动使用for循环将所需要的数据转化成json返回前端。

    user_l = []
    for user_obj in user_list:
        user_l.append(
            json.dumps({'username':user_obj.username,
             'age':user_obj.age,
             'gender':user_obj.get_gender_display()
             })
)

  这样格式的数据一个网站需要处理很多个,使用django自带了一个序列化的模块:

from django.core import serializers
def reg(request):
    user_list = models.User.objects.all()
    res = serializers.serialize('json',user_list)  
    return render(request,'index.html',locals())

  其中注意的是第一个需要传入你所需要的类型,第二个参数是queryset对象。最后渲染的结果是:

    [{
            "model": "app01.user",
            "pk": 1,
            "fields": {
                "username": "jason",
                "age": 18,
                "gender": 1
            }
        }, {
            "model": "app01.user",
            "pk": 2,
            "fields": {
                "username": "tank",
                "age": 24,
                "gender": 3
            }
        }, {
            "model": "app01.user",
            "pk": 3,
            "fields": {
                "username": "egon",
                "age": 73,
                "gender": 2
            }
        }, {
            "model": "app01.user",
            "pk": 7,
            "fields": {
                "username": "kevin",
                "age": 29,
                "gender": 4
            }
    }]

渲染结果

六。删除的确认。 

  在删除数据时,可以设置一个弹窗,将确认这个删除内容,再进行删除操作。

  一般的,可以去这个网站上下载点击按钮样式https://lipis.github.io/bootstrap-sweetalert/

  使用swal关键字就可以定义删除弹窗

<!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>
    {% load static %}
    <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
    <link rel="stylesheet" href="{% static 'dist/sweetalert.css' %}">
    <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>
    <script src="{% static 'dist/sweetalert.min.js' %}"></script>

    <style>
        div.sweet-alert h2{
            padding-top: 10px;
        }
    </style>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <h2 class="text-center">数据展示</h2>
            <table class="table-striped table table-hover table-bordered">
                <thead>
                    <tr>
                        <th>序号</th>
                        <th>主键</th>
                        <th>用户名</th>
                        <th>年龄</th>
                        <th>性别</th>
                        <th>操作</th>
                    </tr>
                </thead>
                <tbody>
                    {% for user in user_list %}
                        <tr>
                            <td>{{ forloop.counter }}</td>
                            <td>{{ user.pk }}</td>
                            <td>{{ user.username }}</td>
                            <td>{{ user.age }}</td>
                            <td>{{ user.get_gender_display }}</td>
                            <td>
                                <button class="btn btn-primary btn-sm">编辑</button>
                                <button class="btn btn-danger btn-sm del" user_id="{{ user.pk }}">删除</button>
                            </td>
                        </tr>
                    {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
</div>
<script>
    $('.del').click(function () {
        // 获取当前标签对象
        var $btnEle = $(this);

        swal({
          title: "你确定要删吗?",
          text: "你要是删了,你就准备跑路吧!",
          type: "warning",
          showCancelButton: true,
          confirmButtonClass: "btn-danger",
          confirmButtonText: "是的,老子就要删!",
          cancelButtonText: "算了,算了!",
          closeOnConfirm: false,
          showLoaderOnConfirm: true
        },
        function(){
            // 朝后端发送ajax请求
            $.ajax({
                url:'',
                type:'post',
                data:{'delete_id':$btnEle.attr('user_id')},
                success:function (data) {  // 后端发字典过来 前端不需要你手动转 会自动帮你转换成js自定义对象
                    if (data.code == 100){
                        {#window.location.href = '';  // 不写就是条到当前页面#}
                        // 通过DOM操作 实时改变页面
                        // 将被点击的删除按钮所在的那一行直接从DOM树中删掉
                        $btnEle.parent().parent().remove();
                        swal("删掉了!", "赶紧回去收拾行李吧,准备跑路!", "success");
                    }else{
                        swal('发生了未知的错误','估计是有bug了','info')
                    }
                }
            });

        });
    })
</script>

</body>
</html>

模板层

from django.http import JsonResponse
import time
def userlist(request):
    if request.is_ajax():
        time.sleep(3)
        """
        一般情况下 针对ajax请求 后端通常都是返回一个字典
        """
        back_dic = {'code':100,'msg':''}
        # 直接获取用户想删除的数据的id值
        delete_id = request.POST.get('delete_id')
        # 直接利用queryset方法 批量删除
        models.User.objects.filter(pk=delete_id).delete()
        # 要给前端ajax返回一个消息(字典)
        back_dic['msg'] = '真的删除了!'
        return JsonResponse(back_dic)

视图层

  注意点:

  1.需要在点击按钮上绑定id,为删除的该数据的主键,再使用js拿到该id传给后端。

  2.返回的字典需要使用json类型的对象,而json对像在前端可以自动转换,不需要反序列化,直接点操作拿出数据。

  3.实时更新的数据可以将删除那一行标签的方法删除。

七。分页器的制作。

  对于大量的数据,可以使用以下方法快速创建:bulk_create(l)

    1 bulk_create()  批量插入数据
        # for i in range(1000):
        #     models.Book.objects.create(title='第%s本书'%i)
        # 上面这种方式 效率极低
        
        l = []
        for i in range(10000):
            l.append(models.Book(title='第%s本书'%i))
        models.Book.objects.bulk_create(l)  # 批量插入数据

  关于分页器的值作:

def fyq(request):
    current_page = request.GET.get('page',1)
    current_page = int(current_page)
    par_page = 10
    start_page = (current_page-1)*par_page
    end_page = start_page+par_page
    all_book = models.User.objects.all()
    # <li><a href="?page=1">1</a></li>
    book_count = all_book.count()
    page_num,more = divmod(book_count,par_page)
    if  more:
        page_num+=1
    html = ''
    if current_page<5:
        current_page = 5
    for i in range(current_page-5,current_page+5):
        html+= '<li><a href="?page=%s">%s</a></li>'%(i+1,i+1)
    res = models.User.objects.all()[start_page:end_page]
    return render(request,'fyq.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>
    {% load static %}
    <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
    <link rel="stylesheet" href="{% static 'dist/sweetalert.css' %}">
    <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>
    <script src="{% static 'dist/sweetalert.js' %}"></script>
</head>
<body>
{% for i in res %}
    <p>{{ i.name }}</p>
{% endfor %}
<nav aria-label="Page navigation">
  <ul class="pagination">
    <li>
      <a href="#" aria-label="Previous">
        <span aria-hidden="true">&laquo;</span>
      </a>
    </li>
{#    <li><a href="?page=1">1</a></li>#}
{#    <li><a href="?page=2">2</a></li>#}
{#    <li><a href="?page=3">3</a></li>#}
{#    <li><a href="?page=4">4</a></li>#}
{#    <li><a href="?page=5">5</a></li>#}
      {{ html|safe }}
    <li>
      <a href="#" aria-label="Next">
        <span aria-hidden="true">&raquo;</span>
      </a>
    </li>
  </ul>
</nav>
</body>
</html>

模板层

  分页器组件:

from app01.utils.mypage import Pagination
def book(request):  
    book_list = models.Book.objects.all()
    current_page = request.GET.get("page",1)
    all_count = book_list.count()
    page_obj = Pagination(current_page=current_page,all_count=all_count,per_page_num=10)
    page_queryset = book_list[page_obj.start:page_obj.end]

试图层

{% for book in page_queryset %}
<p>{{ book.title }}</p>
{% endfor %}
{{ page_obj.page_html|safe }}

模板层