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
AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”。即使用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),
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)
<!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>
4、Ajax实现用户注册校验示例
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^reg2/', views.reg2),
]
<!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>
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)
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})
5、Ajax结合SweetAlert插件示例
点击下载 Bootstrap-sweetalert项目。
点击查看 SweetAlert for Bootstrap详情
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^sweetalert/', views.sweetalert),
]
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
<!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>
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("删除成功!")
三、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); }; });