Django学习【第23篇】:利用Form组件和ajax实现的注册

一、注册相关的知识点

1、Form组件

我们一般写Form的时候都是把它写在views视图里面,那么他和我们的视图函数也不影响,我们可以吧它单另拿出来,在应用下面建一个forms.py的文件来存放

2、局部钩子函数

 def clean_username(self):
        username = self.cleaned_data.get("username")
        valid = models.UserInfo.objects.filter(username = username).first()
        if valid:
            raise ValidationError("用户名已存在")
        return username

3、全局钩子函数

#自定义全局钩子:验证两次密码是否一致
 def clean(self):
   if self.cleaned_data.get("password") == self.cleaned_data.get("password_again"):
        return self.cleaned_data
   else:
        raise  ValidationError("两次密码不一致")

4、 jQuery的属性操作相关的

复制代码
attr:
    一个参数是获取属性的值,两个参数是设置属性值
removeAttr(属性名):
    删除属性值
prop:
    适应于属性的返回值是布尔类型的(单选,反选,取消的例子)
removePorp:
    删除属性的值
复制代码

5、循环的两种方式:

$.each(数组/对象,function(i,v){})
$("div").each(function(i,v){})

6、css中的三种隐藏:

复制代码
1、display:none  隐藏所有内容
2、visibility:hidden 隐藏内容 3、overflow:hidden 隐藏溢出内容 三者都是用来隐藏的: 区别在于: visibility虽然隐藏了,但是被隐藏的内容依然占据这空间,这段隐藏了的内容却保留空间的位置会在网页中显示空白
而display:隐藏了不占用空间 我们在注册的时候不用display:none,不然选择文件的那个功能就没有了,我们可以吧透明度
复制代码

7、提交二进制数据用FormData

复制代码
var formData=new FormData();
formData.append("username",$("#id_username").val()); 
formData.append("email",$("#id_email").val()); formData.append("tel",$("#id_tel").val());
formData.append("password",$("#id_password").val()); formData.append("password_again",$("#id_password_again").val()); formData.append("avatar_img",$("#avatar")[0].files[0]);
复制代码

记得要加上

contentType:false
processData:false

8、可以用下面的方法判断是什么请求

if request.ajax():    #如果ajax请求
if request,method=="POST":   #如果是POST请求

9、上传文件有一个固定的配置参数media,和static相似 但又不同

步骤如下:

- 首先在settings中配置:

# ============media配置===============
MEDIA_URL="/media/"  #别名
MEDIA_ROOT=os.path.join(BASE_DIR,"app01","media","uploads")   #具体路径

- 在url中配置

url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),

用处:

复制代码
用处一:
----- avatar = models.FileField(verbose_name='头像', upload_to='avatar', default="/avatar/default.png") 会把接收的文件放在media指代的路径与upload_to的拼接:BASE_DIR+blog+media+uploads+avatar/a.png avatar字段在数据库中保存的是:avatar/a.png
用处二:
------ <img src="/media/avatar/a.png">

复制代码

如果上传成功会把图片自动保存在这里

10、头像图片预览

复制代码
   //头像预览
        $(".avatar_file").change(function () {
            var ele_file = $(this)[0].files[0]; //当前选中的文件
            var reader = new FileReader();
            reader.readAsDataURL(ele_file); //对应找到打开的url
            reader.οnlοad=function () { {# 方式一#} $(".avatar_img").attr("src",this.result) ; //this.result是上面找到的url {# 方式二#} {# $(".avatar_img")[0].src=this.result; //设置图片属性#}  } })
复制代码

11、form自动生成的错误信息

当你定义了全局钩子的时候,而且正好出现你的那个全局钩子函数中的错(比如两次密码输入不一致),这样你打印错误信息的时候

会有一个__all__对象,这个就是你设置的全局钩子生成的。

所以还要单独判断一下,现在全局钩子只有一个,你可以这样判断,但是,当全局钩子多的时候就得一个一个分开来判断

  if (i=="__all__"){
        $("#id_password_again").after($span)
   }

二、具体实现注册操作

urls.py 

复制代码
 1 from django.conf.urls import url
 2 from django.contrib import admin
 3 from app01 import views
 4 from django.conf import settings
 5 from django.views.static import serve
 6 urlpatterns = [ 7 url(r'^admin/', admin.site.urls), 8 url(r'^login/$', views.login), 9 url(r'^index/$', views.index), 10 url(r'^get_vaildCode_img/$', views.get_vaildCode_img), 11 url(r'^log_out/$', views.log_out), 12 13 url(r'^register/$', views.register), 14 url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}), 15 ]
复制代码

views.py

复制代码
 1 def register(request):
 2     if request.method=="GET":
 3         form = RegisterForm()
 4         return render(request,"register.html",{"form":form})
 5     else:
 6         form = RegisterForm(data=request.POST) 7 regresponse = {"user":None,"msg_errors":None} 8 if form.is_valid(): 9 username = form.cleaned_data.get("username") 10 password = form.cleaned_data.get("password") 11 tel = form.cleaned_data.get("tel") 12 avatar_img = request.FILES.get("avatar_img") 13 print(">>>",username,password,tel) 14 models.UserInfo.objects.create_user(username = username,password=password,tel=tel,avatar=avatar_img) 15 regresponse["user"] = username 16 else: 17 print("form.errors",form.errors) 18 regresponse["msg_errors"]=form.errors 19 return HttpResponse(json.dumps(regresponse))
复制代码

forms.py

复制代码
 1 #!usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 from app01 import models
 4 from django.forms import Form
 5 from django.forms import widgets
 6 from django.forms import fields
 7 from django.core.validators import ValidationError
 8 from django.core.validators import RegexValidator 9 class RegisterForm(Form): 10 username = fields.CharField( 11 required=True, 12 max_length=16, 13 min_length=3, 14 error_messages={ 15 "required": "用户名不能为空", 16 "max_length": "长度不能大于16", 17 "min_length": "长度不能小于3", 18  }, 19 widget=widgets.TextInput({"placeholder":"请您输入用户名","class":"form-control"}) 20  ) 21 password = fields.CharField( 22 required=True, 23 max_length=16, 24 min_length=3, 25 error_messages={ 26 "required": "密码不能为空", 27 "max_length": "长度不能大于16", 28 "min_length": "长度不能小于3", 29  }, 30 widget=widgets.PasswordInput({"placeholder":"请您输入数字与字母组合的密码","class":"form-control"}) 31  ) 32 password_again = fields.CharField( 33 required=True, 34 max_length=16, 35 min_length=3, 36 error_messages={ 37 "required": "密码不能为空", 38 "max_length": "长度不能大于16", 39 "min_length": "长度不能小于3", 40  }, 41 widget=widgets.PasswordInput({"placeholder": "请您再次输入密码", "class": "form-control"}) 42  ) 43 email = fields.EmailField( 44 required=True, 45 error_messages={ 46 "required":"邮箱不能为空", 47 "invalid":"邮箱格式有误" 48  }, 49 widget = widgets.EmailInput({"placeholder": "请输入您的邮箱", "class": "form-control"}) 50  ) 51 tel = fields.CharField( 52 required=True, 53 max_length=11, 54 min_length=11, 55 error_messages={ 56 "required":"手机号码不能为空", 57 "max_length":"长度必须是11位,请你正确输入", 58 "min_length":"长度必须是11位,请你正确输入", 59  }, 60 validators=[RegexValidator("\d+","密码只能是数字")], 61 widget=widgets.TextInput({"placeholder": "请您输入你的电话,要求11位哦", "class": "form-control"}) 62  ) 63 64 #自定义用户名验证:局部钩子 65 def clean_username(self): 66 username = self.cleaned_data.get("username") 67 valid = models.UserInfo.objects.filter(username = username).first() 68 if valid: 69 raise ValidationError("用户名已存在") 70 return username 71 #自定义密码验证: 72 def clean_password(self): 73 password = self.cleaned_data.get("password") 74 if password.isdigit(): 75 raise ValidationError("密码不能是纯数字") 76 else: 77 return password 78 #自定义全局钩子:验证两次密码是否一致 79 def clean(self): 80 if self.cleaned_data.get("password") == self.cleaned_data.get("password_again"): 81 return self.cleaned_data 82 else: 83 raise ValidationError("两次密码不一致")
复制代码

template

复制代码
  1 <!DOCTYPE html>
  2 <html lang="en">
  3 <head>
  4     <meta charset="UTF-8">
  5     <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6     <meta name="viewport" content="width=device-width">
  7     <title>Title</title>
  8     <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
  9     <link rel="stylesheet" href="/static/css/reg.css">
 10 </head>
 11 <body>
 12 {#导航条#}
 13 <nav class="navbar navbar-inverse navbar-fixed-top">
 14     <div class="container pull-left">
 15         <!-- Brand and toggle get grouped for better mobile display -->
 16         <div class="navbar-header">
 17             <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
 18                     data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
 19                 <span class="sr-only">Toggle navigation</span>
 20                 <span class="icon-bar"></span>
 21                 <span class="icon-bar"></span>
 22                 <span class="icon-bar"></span>
 23             </button>
 24             <a class="navbar-brand" href="#">博客园</a>
 25         </div>
 26 
 27         <!-- Collect the nav links, forms, and other content for toggling -->
 28         <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
 29             <ul class="nav navbar-nav">
 30                 <li class="active c1"><a href="#">首页 <span class="sr-only">(current)</span></a></li>
 31                 <li class="active c1"><a href="#">登录</a></li>
 32                 <li class="active c1"><a href="#">注册</a></li>
 33                 <li class="active c1"><a href="#">帮助</a></li>
 34             </ul>
 35         </div><!-- /.navbar-collapse -->
 36     </div><!-- /.container-fluid -->
 37 </nav>
 38 <h2>注册新用户</h2>
 39 <hr>
 40 <div class="container">
 41     <div class="row left">
 42         <div class="col-md-6 col-md-offset-1">
 43             <form action="/register/" method="post" novalidate enctype="multipart/form-data">
 44                 {% csrf_token %}
 45                  <div class="form-group">
 46                     <label for="password" class="control-label">用户名:</label>
 47                     <div>{{ form.username }}<span></span></div>
 48                 </div>
 49                 <div class="form-group">
 50                     <label for="password" class="control-label">密码:</label>
 51                     <div>{{ form.password }}<span></span></div>
 52                 </div>
 53                 <div class="form-group">
 54                     <label for="password" class="control-label">确认密码:</label>
 55                     <div>{{ form.password_again }}<span></span></div>
 56                 </div>
 57                 <div class="form-group">
 58                     <label for="email" class="control-label">邮箱:</label>
 59                     <div>{{ form.email }}<span></span></div>
 60                 </div>
 61                 <div class="form-group">
 62                     <label for="tel" class="control-label">手机号:</label>
 63                     <div>{{ form.tel }}<span></span></div>
 64                 </div>
 65                 <div class="form-group avatar">
 66                     <label for="avatar">头像:</label>
 67                     <img src="/static/image/default.png" alt="" class="avatar_img">
 68                     <input type="file" id="avatar" name="avatar_file" class="avatar_file">
 69                 </div>
 70                 <button type="button" class="btn btn-primary registr_btn">注册</button><span class="xxx"></span>
 71             </form>
 72         </div>
 73     </div>
 74     <div class="right">
 75         <img src="/static/image/rigth.png" alt="">
 76     </div>
 77 </div>
 78 
 79 <script src="/static/jquery-3.2.1.min.js"></script>
 80 <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
 81 <script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.js"></script>
 82 <script>
 83     $(function () {
 84         //给注册按钮增加事件
 85         $(".registr_btn").click(function () {
 86              var formData=new FormData();
 87             formData.append("username",$("#id_username").val()); 88 formData.append("email",$("#id_email").val()); 89 formData.append("tel",$("#id_tel").val()); 90 formData.append("password",$("#id_password").val()); 91 formData.append("password_again",$("#id_password_again").val()); 92 formData.append("avatar_img",$("#avatar")[0].files[0]); 93 console.log("=========",formData); 94 95 //先清除错误信息 96 $(".pull-right").html(""); 97 $(".pull-right").parent().removeClass("has-error"); 98  $.ajax({ 99 url:"/register/", 100 type:"POST", 101 headers: {"X-CSRFToken": $.cookie('csrftoken')}, 102  data:formData, 103 contentType:false, 104 processData:false, 105 success:function (data) { 106 {# console.log(data);#} 107 var data = JSON.parse(data); 108 if(data["user"]){ //或者也可以用data.user 109 $(".xxx").html("注册成功"); 110 window.location.href="/login/"; 111  } 112 else { 113 console.log(data.msg_errors); //拿到的是所有的错误信息 114 $.each(data.msg_errors,function (i,v) { 115  console.log(i,v); 116 $span = $("<span>");//创建一个span标签,方便提示错误信息的时候用 117 $span.addClass("pull-right").css("color","red"); //设置样式居右并且字体颜色为红色 118 $span.html(v[0]);//设置span里面的字体 119 $("#id_"+i).after($span).parent().addClass("has-error");//吧span标签放到每个input的后面显示并且让他的父亲变红,增加一个has-error的类 120 121 if (i=="__all__"){ 122 $("#id_password_again").after($span) 123  } 124  }); 125  } 126  } 127  }) 128  }); 129 130 //头像预览 131 $(".avatar_file").change(function () { 132 var ele_file = $(this)[0].files[0]; //当前选中的文件 133 var reader = new FileReader(); 134 reader.readAsDataURL(ele_file); //对应找到打开的url 135 reader.οnlοad=function () { 136 {# 方式一#} 137 $(".avatar_img").attr("src",this.result) ; //this.result是上面找到的url 138 {# 方式二#} 139 {# $(".avatar_img")[0].src=this.result; //设置图片属性#} 140  } 141  }) 142  }) 143 </script> 144 </body> 145 </html>
复制代码
复制代码
 1 .c1 {
 2     margin-right: 10px;
 3 }
 4 
 5 h2 {
 6     margin-top: 100px;
 7     margin-left: 280px; 8 } 9 .left{ 10  position: relative; 11 } 12 .right{ 13  width: 270px; 14  height: 294px; 15  position: absolute; 16  top: 197px; 17  left: 886px; 18 } 19 .registr_btn{ 20  width: 100px; 21 margin-left: 200px; 22 } 23 .avatar{ 24  position: relative; 25  width: 70px; 26  height: 70px; 27 } 28 .avatar_img,.avatar_file{ 29  position: absolute; 30  width: 70px; 31  height: 70px; 32 top: 0; 33  left: 46px; 34 } 35 .avatar_file{ 36 opacity: 0; 37 }
复制代码

 效果截图

 

转载于:https://www.cnblogs.com/kcwxx/p/10156435.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值