Django与AJAX-choice字段-MTV和MVC模型-sweetalert搭建页面

Django中的choice字段

  应用的场景:

    用户信息举列:如用户性别、婚否、学历、工作状态等可以列举出来供选择的信息

书写models创建表模型:

Django与AJAX-choice字段-MTV和MVC模型-sweetalert搭建页面_第1张图片

数据的获取和查询:

Django与AJAX-choice字段-MTV和MVC模型-sweetalert搭建页面_第2张图片

 

 总结:

"""
      1 存choice里面罗列的数字与中文对应关系
           print(user_obj.get_gender_display())
              只要是choices字段 在获取数字对应的数据 固定语法
              get_choices字段名_display()

      2 存没有罗列出来的数字
          不会报错 还是展示数字
      """

MTV和MVC框架 (了解概念)

MVC(Model View Controller 模型-视图-控制器)

MTV(Model Templates View 模型-模板-视图):

区别:

MVC中的View的目的是「呈现哪一个数据」,而MTV的View的目的是「数据如何呈现」。

   MTV:是Django框架,自己自称的

    M:models模型

    T:templates模板

    V:views视图

   MVC:目前大部分web框架的本质

    M:models

    V:views

    C:controller  控制器(urls)

本质:MTV其实也是MVC

Django与AJAX

  关键理解:异步提交,局部刷新

例如github官网的注册界面:

  注册用户名时,时刻监测用户名是否存在,向后端发送请求,进行动态的校验.

Django与AJAX-choice字段-MTV和MVC模型-sweetalert搭建页面_第3张图片

目前所接触到的向后端发送请求方式:

  GET/POST请求

"""
前端中的 标签 >>>>>GET请求       
浏览器中输入的url搜索>>>>>GET请求  
from表单  >>>>>>>>>>>>>>>GET/POST请求
AJAX》>>>>>>>>>>>>>>>>>GET/POST请求

"""

 

AJAX简介

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

AJAX 不是新的编程语言,而是一种使用现有标准的新方法。

AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)

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

  • 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
  • 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。

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

例子:

  页面上有三个input框,在前两个input框中输入数字,点击按钮 发送ajax请求,不刷新页面的情况下,第三个框中自动算出两数之和。

前端向后端发送请求需注意:改成让Django知道走POST请求

Django与AJAX-choice字段-MTV和MVC模型-sweetalert搭建页面_第4张图片

 views.py

from django.shortcuts import render,reverse,HttpResponse,redirect

# Create your views here.

def index(request):
    print(request.is_ajax())  # 用来判断当前请求方式是否是ajax请求
    if request.is_ajax():
        if request.method == 'POST':
            # print(request.POST)
            i1 = request.POST.get('i1')
            i2 = request.POST.get('i2')

            # 后端获取的前端数据 都是字符串格式
            res = int(i1) + int(i2)
            return HttpResponse(res)
        return reverse(request,'index.html')

url,py

from django.conf.urls import url
from django.contrib import admin
from app01 import views


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/',views.index),
]

index.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
     <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://cdn.bootcss.com/jquery/3.4.0/jquery.slim.js">script>
head>
<body>
<input type="text" id="l1">+<input type="text" id="l2">=<input type="text" id="l3">
<button id="l3">求和button>
<script> // 绑定点击事件
    $('#l3').on('click',function () {
                {#alert(123)#}
                // 点击按钮 朝后端发送post请求
                $.ajax({
                    url:'',  // 控制发送给谁 不写就是朝当前地址提交
                    type:'post',  // 发送方式是post请求
                    data:{'i1':$('#l1').val(),'l2':$('#l2').val()},  // 发送的数据
                    success:function (data) {  // data形参用来接收异步提交的结果
                        // 将后端计算好的结果 通过DOM操作 渲染到第三个input框中
                        $('#l3').val(data)
                    }
                })
            })
script>
body>
html>

前端书写AJAX部分

Django与AJAX-choice字段-MTV和MVC模型-sweetalert搭建页面_第5张图片

运行的结果是:点击求和后向后端发送POST请求,取到结果并展示

Django与AJAX-choice字段-MTV和MVC模型-sweetalert搭建页面_第6张图片

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

常用的数据编码格式有三类:

1.urlencoded  >>>>>  数据格式:name=jack&pwd=123&boby=running
2.formdata    >>>>>>>>>     传文件也支持传普通的键值对:name=jack&pwd=123&boby=running
3.json     >>>>>>>>       josn格式数据(from表单是无法发送Json格式的数据的)

 

  form 表单:默认使用的编码格式是urlencoded,数据格式是:name=jason&pwd=123;发送到后端,

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

可以修改为formdata 传文件
      django后端针对只要是符合urlencoded编码格式的数据(name=jason&pwd=123)都会自动解析并放到request.POST中供用户获取

如果是文件 只要你指定的编码是formdata 就会自动解析并放到request.FILES中

Django与AJAX-choice字段-MTV和MVC模型-sweetalert搭建页面_第7张图片

 

ajax提交数据:提交的方式默认也是urlencoded

django后端针对不同的编码格式是如何处理的?

1、只要是符合urlencoded编码格式  都会被后端自动获取并解析放到request.POST中
2、如果是符合formdata那么文件会自动被解析放到request.FILES中
3、如果是json格式 后端默认不解析 以二进制的形式就放在request.body你可以自己手动处理即可

ajax发送json格式数据

<script>
    $('#b1').on('click',function () {
        alert(123)
        // 点击按钮 朝后端发送post请求
        $.ajax({
            url:'',  // 控制发送给谁 不写就是朝当前地址提交
            type:'post',  // 发送方式是post请求
            data:JSON.stringify({'username':'jason','password':123}),  // 发送的数据
            contentType:'application/json',  // 告诉后端你这次的数据是json格式

            success:function (data) {  // data形参用来接收异步提交的结果
                alert(data)
                // 将后端计算好的结果 通过DOM操作 渲染到第三个input矿中
                $('#i3').val(data)
            }

        })
    // {)
script>

 要指定传输的数据格式统一

Django与AJAX-choice字段-MTV和MVC模型-sweetalert搭建页面_第8张图片

后端验证数据格式:

def index(request):

#验证前后端传输数据的编码格式
    if request.method =='POST':
        print('request.POST',request.POST)
        print('request.FILES',request.FILES)
        jason_str = request.body
        import json
        # 后端 需要手动去request.body中获取json格式数据 自己处理
        res = jason_str.decode('utf-8')
        ral_d = json.loads(res)
        print(ral_d)
        return HttpResponse('OK')
    return render(request,'index.html')

 

总结:前后端在传输数据的时候,一定要保证数据格式和你的编码保持一致性的.

通常情况下,后端针对ajax交互,都是采取字典的形式

基于AJAX传文件:

  关键字formData

传文件:如何获取文件标签存储的问文件对象?固定的语法

  1、先用jQuery查找到存储文件的input标签

  2、将jQuery对象转成原生Javascript对象

  3、利用原生Javascript对象的方法.files[0]获取到标签内部存储的文件对象

{#// ajax传输文件#}
    $('#b1').on('click',function () {
        // ajax传输文件 建议使用内置对象formdata
        var formData = new FormData();  // 既可以传普通的键值对 也可以传文件
        // 添加普通键值
        formData.append('username','jason');
        formData.append('password','123');
        //固定的格式
        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形参用来接收异步提交的结果
                alert(data)
                // 将后端计算好的结果 通过DOM操作 渲染到第三个input矿中
                $('#i3').val(data)
            }

        })

 

注意固定的格式及一些参数的使用

序列化组件

  Django内置的serializers

  简单的解释就是前端想拿到由ORM得到数据库中里面得一个个用户对象,为了简便操作,

后端直接将实例化出来的数据对象直接发送给客户端,这时候就需要用到序列化模块。

主要是考虑Json序列化字典的数据格式,传输的数据类型比较多,也可以以K:V键值对的形式取值。

from django.core import serializers  # django自带的一个小型的序列化工具
def reg(request):
    user_list = models.User.objects.all()
  原来的数据传输:
# 将所有的数据都组织成一个符合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() # }) # ) res = serializers.serialize('json',user_list) # return render(request,'index.html',locals())

 利用在这json在线格式转换工具:

Django与AJAX-choice字段-MTV和MVC模型-sweetalert搭建页面_第9张图片

 

 AJAX结合sweetalert插件的应用(动态弹框)

  实现以下的动态弹框提示,点击下载Bootstrap-sweetalert项目。需要导入的插件,统一放入static文件中配置到settings.py文件下.

Django与AJAX-choice字段-MTV和MVC模型-sweetalert搭建页面_第10张图片

 

views.py

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)


    user_list = models.User.objects.all()
    return render(request,'userlist.html',locals())

userlist.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <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>

效果如下:

Django与AJAX-choice字段-MTV和MVC模型-sweetalert搭建页面_第11张图片

 

 

自定义分页器

直接拷贝代码然后导入使用即可:

class Pagination(object):
    def __init__(self, current_page, all_count, per_page_num=2, pager_count=11):
        """
        封装分页相关数据
        :param current_page: 当前页
        :param all_count:    数据库中的数据总条数
        :param per_page_num: 每页显示的数据条数
        :param pager_count:  最多显示的页码个数

        用法:
        queryset = model.objects.all()
        page_obj = Pagination(current_page,all_count)
        page_data = queryset[page_obj.start:page_obj.end]
        获取数据用page_data而不再使用原始的queryset
        获取前端分页样式用page_obj.page_html
        """
        try:
            current_page = int(current_page)
        except Exception as e:
            current_page = 1

        if current_page < 1:
            current_page = 1

        self.current_page = current_page

        self.all_count = all_count
        self.per_page_num = per_page_num

        # 总页码
        all_pager, tmp = divmod(all_count, per_page_num)
        if tmp:
            all_pager += 1
        self.all_pager = all_pager

        self.pager_count = pager_count
        self.pager_count_half = int((pager_count - 1) / 2)

    @property
    def start(self):
        return (self.current_page - 1) * self.per_page_num

    @property
    def end(self):
        return self.current_page * self.per_page_num

    def page_html(self):
        # 如果总页码 < 11个:
        if self.all_pager <= self.pager_count:
            pager_start = 1
            pager_end = self.all_pager + 1
        # 总页码  > 11
        else:
            # 当前页如果<=页面上最多显示11/2个页码
            if self.current_page <= self.pager_count_half:
                pager_start = 1
                pager_end = self.pager_count + 1

            # 当前页大于5
            else:
                # 页码翻到最后
                if (self.current_page + self.pager_count_half) > self.all_pager:
                    pager_end = self.all_pager + 1
                    pager_start = self.all_pager - self.pager_count + 1
                else:
                    pager_start = self.current_page - self.pager_count_half
                    pager_end = self.current_page + self.pager_count_half + 1

        page_html_list = []
        # 添加前面的nav和ul标签
        page_html_list.append('''
                    
                                           
                                       ''')
        return ''.join(page_html_list)

 

导入使用

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]

    return render(request,'booklist.html',locals())

 

booklist.html


"en">

    "UTF-8">
    Title
    
    {% load static %}
    "stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
    "stylesheet" href="{% static 'dist/sweetalert.css' %}">
    
    


class="container">
class="row">
class="col-md-8 col-md-offset-2"> {% for book in page_queryset %}

{{ book.title }}

{% endfor %} {{ page_obj.page_html|safe }}

 

 

 

 

 

 

 

  

 

 

 

 

 

 

 

 

 

 

 

 

 

  

 

你可能感兴趣的:(Django与AJAX-choice字段-MTV和MVC模型-sweetalert搭建页面)