Ajax + Django的Form

一、Json复习

  合格的json对象:

["one", "two", "three"]
{ "one": 1, "two": 2, "three": 3 }
{"names": ["张三", "李四"] }
[ { "name": "张三"}, {"name": "李四"} ] 

   不合格的json对象:

{ name: "张三", 'age': 32 }                    // 属性名必须使用双引号
[32, 64, 128, 0xFFF]                          // 不能使用十六进制值
{ "name": "张三", "age": undefined }          // 不能使用undefined
{ "name": "张三",
  "birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'),
  "getName":  function() {return this.name;}             // 不能使用函数和日期对象
}

二、Ajax

  AJAXAsynchronous Javascript And XML)翻译成中文就是异步的JavascriptXML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。AJAX 不是新的编程语言,而是一种使用现有标准的新方法。

1、Ajax优点

  • AJAX使用JavaScript技术向服务器发送异步请求;
  • AJAX请求无须刷新整个页面;
  • 因为服务器响应内容不再是整个页面,而是页面中的部分内容,所以AJAX性能高; 
  • AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。

2、Ajax传带文件的数据注意事项:

  (1)processData: false,

     contentType: false,

  (2)data: formData

// AJAX提交注册的数据
    $("#reg-submit").click(function () {
        // 取到用户填写的注册数据,向后端发送AJAX请求
        var formData = new FormData();
        formData.append("username", $("#id_username").val());
        formData.append("password", $("#id_password").val());
        formData.append("re_password", $("#id_re_password").val());
        formData.append("email", $("#id_email").val());
        formData.append("avatar", $("#id_avatar")[0].files[0]);
        formData.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val());

        $.ajax({
            url: "/reg/",
            type: "post",
            processData: false,
            contentType: false,
            data: formData,
            success:function (data) {
                if (data.status){
                    // 有错误就展示错误
                    // console.log(data.msg);
                    // 将报错信息填写到页面上
                    $.each(data.msg, function (k,v) {
                        // console.log("id_"+k, v[0]);
                        // console.log($("#id_"+k));
                        $("#id_"+k).next("span").text(v[0]).parent().parent().addClass("has-error");
                    })

                }else {
                    // 没有错误就跳转到指定页面
                    location.href = data.msg;
                }
            }
        })
    });

3、Ajax常见应用场景

  搜索引擎根据用户输入的关键字,自动提示检索关键字。

  还有一个很重要的应用场景就是:注册时候的用户名的查重。

其实这里就使用了AJAX技术!当文件框发生了输入变化时,使用AJAX技术向服务器发送一个请求,然后服务器会把查询到的结果响应给浏览器,最后再把后端返回的结果展示出来

  • 整个过程中页面没有刷新,只是刷新页面中的局部位置而已!
  • 当请求发出后,浏览器还可以进行其他操作,无需等待服务器的响应!

3、Ajax实现计算机示例

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

urlpatterns = [
    url(r'^index/', views.index),
    url(r'^ajax_add/', views.ajax_add),
    url(r'^ajax_add_post/', views.ajax_add_post),
urls.py
from django.shortcuts import render,HttpResponse
from . import models
import json
from django.core import serializers
# Create your views here.

def index(request):
    return render(request,"index.html")

# get请求
def ajax_add(request):
    i1 = request.GET.get("i1")
    i2 = request.GET.get("i2")
    i1 = int(i1)
    i2 = int(i2)
    ret = i1 + i2
    return HttpResponse(ret)

#post请求
def ajax_add_post(request):
    i1 = request.POST.get("i1")
    i2 = request.POST.get("i2")
    i1 = int(i1)
    i2 = int(i2)
    ret = i1 + i2
    return HttpResponse(ret)
views.py
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="x-ua-compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>AJAX局部刷新实例</title>
</head>
<body>

{#{% csrf_token %}#}
<input type="text" id="i1">+
<input type="text" id="i2">=
<input type="text" id="i3">
<input type="button" value="AJAX提交" id="b1">
<input type="button" value="AJAX_POST提交" id="b3">
<input type="button" value="呵呵哒" id="b2">

<script src="/static/jquery-3.2.1.min.js"></script>
<script src="/static/setup_ajax.js"></script>
<script>
  $("#b1").on("click", function () {
      var i1 = $("#i1").val();
      var i2 = $("#i2").val()
    $.ajax({
        url:"/ajax_add/",
        type:"GET",
        data:{"i1":i1,"i2":i2},
        success:function(data){                 {#成功返回一个匿名函数#}
            $("#i3").val(data)
        }
    })
  })

    $("#b3").on("click", function () {
      var i1 = $("#i1").val();
      var i2 = $("#i2").val()
      {#var csrfToken = $("[name = 'csrfmiddlewaretoken']").val()    //找到页面上csrf_token#}

    $.ajax({
        url:"/ajax_add_post/",
        type:"POST",
        data:{"i1":i1,"i2":i2},
        success:function(data){                 {#成功返回一个匿名函数#}
            $("#i3").val(data)
        }
    })
  })


    $("#b2").on("click",function () {
        $.ajax({
            url:"/test/",
            type:"GET",
            success:function(data){
                //在页面上创建一个标签
                var imgEle = document.createElement("img");
                imgEle.src = data;
                //吧创建的html标签添加到文档中
                $("#b2").after(imgEle);
            }
        })
    })
</script>
</body>
</html>
index.html

4、Ajax实现用户注册校验示例

from django.conf.urls import url
from app01 import views
urlpatterns = [
    url(r'^reg2/', views.reg2),
]
urls.py
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta name='description' content="内容" http-equiv="refresh" charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>注册</title>
    <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <form action="/reg2/" method="post" novalidate class="form-horizontal">
                {% csrf_token %}
                <div class="form-group {% if form_obj.name.errors.0 %}has-error{% endif %}">
                    <label class="control-label">{{ form_obj.name.label }}</label>
                    {{ form_obj.name }}
                    <span class="help-block">{{ form_obj.name.errors.0 }}</span>
                </div>

                <div class="form-group {% if form_obj.email.errors.0 %}has-error{% endif %}">
                    <label class="control-label">{{ form_obj.email.label }}</label>
                    {{ form_obj.email }}
                    <span class="help-block">{{ form_obj.email.errors.0 }}</span>
                </div>

                <div class="form-group {% if form_obj.phone.errors.0 %}has-error{% endif %}">
                    <label class="control-label">{{ form_obj.phone.label }}</label>
                    {{ form_obj.phone }}
                    <span class="help-block">{{ form_obj.phone.errors.0 }}</span>
                </div>

                <div class="form-group {% if form_obj.pwd.errors.0 %}has-error{% endif %}">
                    <label class="control-label">{{ form_obj.pwd.label }}</label>
                    {{ form_obj.pwd }}
                    <span class="help-block">{{ form_obj.pwd.errors.0 }}</span>
                </div>

                <div class="form-group {% if form_obj.re_pwd.errors.0 %}has-error{% endif %}">
                    <label class="control-label">{{ form_obj.re_pwd.label }}</label>
                    {{ form_obj.re_pwd }}
                    <span class="help-block">{{ form_obj.re_pwd.errors.0 }}</span>
                </div>

                <div class="form-group">
                    <input type="submit" class="btn btn-primary">
                </div>
            </form>
        </div>
    </div>
</div>

<script src="/static/jquery-3.2.1.min.js"></script>
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
</body>
</html>
reg2.html
class Userinfo(models.Model):
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=16)
    email = models.EmailField(null=True,default="gogogo@163.com")
    phone = models.CharField(null=False,default="13902345678",max_length=11)
mdoels.py
from django.shortcuts import render,HttpResponse
from . import models

#      Django Form组件的使用
from django import forms
from django.forms import widgets
from django.core.validators import RegexValidator           #字段校验
from django.core.exceptions import ValidationError          #验证

class RegForm(forms.Form):
    name = forms.CharField(
        label="用户名",
        max_length=16,
        # widget控制的是生成html代码相关的插件
        widget=widgets.TextInput(attrs={"class":"form-control"}),   #  <input type="email" class="form-control" id="inputEmail3" placeholder="Email">
        error_messages = {
                         "required": "该字段不能为空",
                     }
    )
    email = forms.EmailField(
        label ="邮箱",
        widget = widgets.TextInput(attrs={"class": "form-control"}),
        error_messages = {
        "required": "该字段不能为空",
        }
    )
    phone = forms.CharField(
        label="手机",
        widget=widgets.TextInput(attrs={"class": "form-control"}),
        validators=[
            RegexValidator(r'^[0-9]+$', '手机号必须是数字'),
            RegexValidator(r'^1[3-9][0-9]{9}$', '手机号格式不正确')
        ],
        error_messages={
            "required": "该字段不能为空",
        }
    )
    pwd = forms.CharField(
        label="密码",
        min_length=6,
        max_length=10,
        widget = widgets.PasswordInput(attrs={"class":"form-control"},render_value=True),
        error_messages={
            "min_length": "密码不能少于6位!",
            "required": "密码不能为空",
            "invalid": "格式错误",
            "max_length": "密码最长12位",
            }
        )
    re_pwd = forms.CharField(
        label="确认密码",
        min_length=6,
        max_length=10,
        widget=widgets.PasswordInput(attrs={"class": "form-control"}, render_value=True),
        error_messages={
            "required": "该字段不能为空",
            "invalid": "输入的两次密码不一致",
            "min_length": "密码不能少于6位!",
            "max_length": "密码最长10位!",
        }
    )
    # city = forms.ChoiceField(
    #     choices=models.City.objects.all().values_list("id","name"),
    #     label="城市",
    #     initial=1,
    #     widget=forms.widgets.Select
    # )

    #choices的选项可以配置从数据库中获取,但是由于是静态字段 获取的值无法实时更新,需要重写构造方法从而实现choice实时更新
    # def __init__(self,*args, **kwargs):
    #     super().__init__(*args, **kwargs)
    #     self.fields["city"].widget.choices = models.City.objects.all().values_list("id","name")


    # 定义局部钩子Hook,用来校验username字段
    def clean_name(self):
        value = self.cleaned_data.get("name")
        if "金瓶" in value:
            raise ValidationError("不符合社会主义核心价值观!")
        return value

    # 定义全局的钩子,用来校验密码和确认密码字段是否相同
    def clean(self):
        # 此时 通过检验的字段的数据都保存在 self.cleaned_data
        pwd = self.cleaned_data.get("pwd")
        re_pwd = self.cleaned_data.get("re_pwd")
        if pwd != re_pwd:
            self.add_error("re_pwd", ValidationError("两次密码不一致"))
            raise ValidationError("两次密码不一致")
        return self.cleaned_data

def reg2(request):
    form_obj = RegForm()

    if request.method == "POST":
        form_obj = RegForm(request.POST)
        if form_obj.is_valid():

            # 校验过的数据,保存到数据库中,存在form_obj.cleaned_data(是一个字典)
            #print(form_obj.cleaned_data)  # {'name': '金瓶', 'email': 'qwe212@123.COM', 'phone': '15662286158', 'pwd': 'zxcvbnm', 're_pwd': 'zxcvbnm'}
            # ** kwargs: a=1, b=2, c=3    ==>   kwargs =  {'a': 1, 'b': 2, 'c': 3}
            # models.UserInfo.objects.create(user='rose', pwd='123456')

            del form_obj.cleaned_data["re_pwd"]
            models.Userinfo.objects.create(**form_obj.cleaned_data)
            return HttpResponse("登录成功")

    return render(request,"reg2.html",{"form_obj":form_obj})
views.py

5、Ajax结合SweetAlert插件示例

 点击下载  Bootstrap-sweetalert项目

点击查看   SweetAlert for Bootstrap详情

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

urlpatterns = [
    url(r'^sweetalert/', views.sweetalert),
]
urls.py
from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    birthday = models.DateField(auto_now_add=True)
    def __str__(self):
        return self.name
models.py
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta name='description' content="内容" http-equiv="refresh" charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>sweetalert</title>
    <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
    <link rel="stylesheet" href="/static/fontAwesome/css/font-awesome.min.css">
    <link rel="stylesheet" href="/static/sweetalert/sweetalert.css">
    <style>
        .sweet-alert > h2 {
            padding-top: 15px;
        }
    </style>
</head>
<body>
<div class="container">
    <div class="panel panel-primary">
        <div class="panel-heading">
            <h3 class="panel-title">Person 管理</h3>
        </div>
        <div class="panel-body">
            <div class="bs-example" data-example-id="hoverable-table">
                <table class="table table-hover">
                    <thead>
                    <tr>
                        <th>序号</th>
                        <th>id</th>
                        <th>name</th>
                        <th>年龄</th>
                        <th>生日</th>
                    </tr>
                    </thead>
                    <tbody>
                    {% for p in persons %}
                        <tr>
                            <td>{{ forloop.counter }}</td>
                            <td>{{ p.id }}</td>
                            <td>{{ p.name }}</td>
                            <td>{{ p.age }}</td>
                            <td>{{ p.birthday|date:"Y-m-d" }}</td>
                            <td>
                                <button class="btn btn-danger del"><i class="fa fa-trash"> 删除</i></button>
                            </td>
                        </tr>
                    {% endfor %}
                    </tbody>
                </table>
            </div>
        </div>
    </div>
</div>

<p>
  <button type="button" class="btn btn-primary btn-lg b1">点我</button>
</p>
<hr>

<p>
   <input type="text" id="i1" name="name">
    <span id="e1"></span>
</p>


<script src="/static/jquery-3.2.1.min.js"></script>
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
<script src="/static/sweetalert/sweetalert.min.js"></script>
<script src="/static/setup_ajax.js"></script>
<script>
    {#    找到删除按钮, 绑定事件#}
    // language=JQuery-CSS
    $(".del").on("#click", function () {
        var $tr_ele = $(this).parent().parent();
        var del_id = $tr_ele.children().eq(1).text();
        swal({
                title: "你确定要删除吗?",
                text: "一旦删除就找不回来了",
                type: "warning",
                showCancelButton: true,
                showLoaderOnConfirm: true,
                confirmButtonClass: "btn-danger",
                confirmButtonText: "确认",
                cancelButtonText: "取消",
                closeOnConfirm: false
            },
        function () {              {#向后端发送删除的请求#}
            $.ajax({
                url: "/delete/",
                type:"post",
                data:{"id":del_id},
                success:function(arg){
                    swal(arg, "准备好跑路吧", "success");
                    $tr_ele.remove();
                }
            })
        });
    })

    {#    找到 i1 标签,绑定事件 #}
    $("#i1").blur(function () {                  //到 i1 标签,绑定失去焦点的事件
    //$("#i1").on("input",function () {          //找到 i1 标签,绑定input实时判断 事件
        var $i1Ele = $(this);
        var name = $i1Ele.val();       // 取到input框的值

        $("#e1").text("");          // 将i1后面的span中的内容置为空,为了清除上次填充的内容

        $.ajax({
            url:"/check_user/",
            type:"post",
            data:{"name":name},
            datatype:"json",
            success:function (arg) {
                $("#e1").text(arg).css("color","red");
            }
        })

    })
</script>
</body>
</html>
sweetalert.html
from django.shortcuts import render,HttpResponse
from . import models
from django.core import serializers

def persons(request):
    ret = models.Person.objects.all()
    # persion_list = []
    # for i in ret:
    #     persion_list.append({"name":i.name,"age":i.age})
    # print(persion_list)
    # import json
    # str = json.dumps(persion_list)
    # print(str)
    s = serializers.serialize("json",ret)
    print(s)
    return HttpResponse(s)

def sweetalert(request):
    ret = models.Person.objects.all()
    return render(request,"sweetalert.html",{"persons":ret})

def delete(request):
    import time
    time.sleep(3)
    del_id = request.POST.get("id")
    models.Person.objects.filter(id =del_id).delete()
    return HttpResponse("删除成功!")
views.py

 三、Django Form和ModelForm组件

  form组件和文件上传注意事项:

(1)form表单一定要设置 enctype = "multipart/form-data"

(2)视图函数中,取数据:

  file_obj = request.FILES.get("name")

  file_obj.name ——> 文件名

  扩展:FileReader

// 找到头像的input标签绑定change事件
    $("#id_avatar").change(function () {
        // 1. 创建一个读取文件的对象
        var fileReader = new FileReader();
        // 取到当前选中的头像文件
        // console.log(this.files[0]);
        // 读取你选中的那个文件
        fileReader.readAsDataURL(this.files[0]);  // 读取文件是需要时间的
        fileReader.onload = function () {
            // 2. 等上一步读完文件之后才 把图片加载到img标签中
            $("#avatar-img").attr("src", fileReader.result);
        };
    });
原文地址:https://www.cnblogs.com/timetellu/p/10860209.html