Django 【第十七篇】使用Form組件和Ajax實現用戶註冊
阿新 • • 發佈:2018-02-21
紅色 abs form 實現 效果 郵箱 具體實現 addclass 增加
一、註冊相關的知識點
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.onload=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
from django.conf.urls import url from django.contrib import admin from app01 import views from django.conf import settings from django.views.static import serve urlpatterns = [ url(r‘^admin/‘, admin.site.urls), url(r‘^login/$‘, views.login), url(r‘^index/$‘, views.index), url(r‘^get_vaildCode_img/$‘, views.get_vaildCode_img), url(r‘^log_out/$‘, views.log_out), url(r‘^register/$‘, views.register), url(r‘^media/(?P<path>.*)$‘, serve, {‘document_root‘: settings.MEDIA_ROOT}), ]
views.py
def register(request): if request.method=="GET": form = RegisterForm() return render(request,"register.html",{"form":form}) else: form = RegisterForm(data=request.POST) regresponse = {"user":None,"msg_errors":None} if form.is_valid(): username = form.cleaned_data.get("username") password = form.cleaned_data.get("password") tel = form.cleaned_data.get("tel") avatar_img = request.FILES.get("avatar_img") print(">>>",username,password,tel) models.UserInfo.objects.create_user(username = username,password=password,tel=tel,avatar=avatar_img) regresponse["user"] = username else: print("form.errors",form.errors) regresponse["msg_errors"]=form.errors return HttpResponse(json.dumps(regresponse))
forms.py
#!usr/bin/env python # -*- coding:utf-8 -*- from app01 import models from django.forms import Form from django.forms import widgets from django.forms import fields from django.core.validators import ValidationError from django.core.validators import RegexValidator class RegisterForm(Form): username = fields.CharField( required=True, max_length=16, min_length=3, error_messages={ "required": "用戶名不能為空", "max_length": "長度不能大於16", "min_length": "長度不能小於3", }, widget=widgets.TextInput({"placeholder":"請您輸入用戶名","class":"form-control"}) ) password = fields.CharField( required=True, max_length=16, min_length=3, error_messages={ "required": "密碼不能為空", "max_length": "長度不能大於16", "min_length": "長度不能小於3", }, widget=widgets.PasswordInput({"placeholder":"請您輸入數字與字母組合的密碼","class":"form-control"}) ) password_again = fields.CharField( required=True, max_length=16, min_length=3, error_messages={ "required": "密碼不能為空", "max_length": "長度不能大於16", "min_length": "長度不能小於3", }, widget=widgets.PasswordInput({"placeholder": "請您再次輸入密碼", "class": "form-control"}) ) email = fields.EmailField( required=True, error_messages={ "required":"郵箱不能為空", "invalid":"郵箱格式有誤" }, widget = widgets.EmailInput({"placeholder": "請輸入您的郵箱", "class": "form-control"}) ) tel = fields.CharField( required=True, max_length=11, min_length=11, error_messages={ "required":"手機號碼不能為空", "max_length":"長度必須是11位,請你正確輸入", "min_length":"長度必須是11位,請你正確輸入", }, validators=[RegexValidator("\d+","密碼只能是數字")], widget=widgets.TextInput({"placeholder": "請您輸入你的電話,要求11位哦", "class": "form-control"}) ) #自定義用戶名驗證:局部鉤子 def clean_username(self): username = self.cleaned_data.get("username") valid = models.UserInfo.objects.filter(username = username).first() if valid: raise ValidationError("用戶名已存在") return username #自定義密碼驗證: def clean_password(self): password = self.cleaned_data.get("password") if password.isdigit(): raise ValidationError("密碼不能是純數字") else: return password #自定義全局鉤子:驗證兩次密碼是否一致 def clean(self): if self.cleaned_data.get("password") == self.cleaned_data.get("password_again"): return self.cleaned_data else: raise ValidationError("兩次密碼不一致")
template
register.html<!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"> <title>Title</title> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/css/reg.css"> </head> <body> {#導航條#} <nav class="navbar navbar-inverse navbar-fixed-top"> <div class="container pull-left"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">博客園</a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li class="active c1"><a href="#">首頁 <span class="sr-only">(current)</span></a></li> <li class="active c1"><a href="#">登錄</a></li> <li class="active c1"><a href="#">註冊</a></li> <li class="active c1"><a href="#">幫助</a></li> </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav> <h2>註冊新用戶</h2> <hr> <div class="container"> <div class="row left"> <div class="col-md-6 col-md-offset-1"> <form action="/register/" method="post" novalidate enctype="multipart/form-data"> {% csrf_token %} <div class="form-group"> <label for="password" class="control-label">用戶名:</label> <div>{{ form.username }}<span></span></div> </div> <div class="form-group"> <label for="password" class="control-label">密碼:</label> <div>{{ form.password }}<span></span></div> </div> <div class="form-group"> <label for="password" class="control-label">確認密碼:</label> <div>{{ form.password_again }}<span></span></div> </div> <div class="form-group"> <label for="email" class="control-label">郵箱:</label> <div>{{ form.email }}<span></span></div> </div> <div class="form-group"> <label for="tel" class="control-label">手機號:</label> <div>{{ form.tel }}<span></span></div> </div> <div class="form-group avatar"> <label for="avatar">頭像:</label> <img src="/static/image/default.png" class="avatar_img"> <input type="file" id="avatar" name="avatar_file" class="avatar_file"> </div> <button type="button" class="btn btn-primary registr_btn">註冊</button><span class="xxx"></span> </form> </div> </div> <div class="right"> <img src="/static/image/rigth.png" > </div> </div> <script src="/static/jquery-3.2.1.min.js"></script> <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script> <script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.js"></script> <script> $(function () { //給註冊按鈕增加事件 $(".registr_btn").click(function () { 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]); console.log("=========",formData); //先清除錯誤信息 $(".pull-right").html(""); $(".pull-right").parent().removeClass("has-error"); $.ajax({ url:"/register/", type:"POST", headers: {"X-CSRFToken": $.cookie(‘csrftoken‘)}, data:formData, contentType:false, processData:false, success:function (data) { {# console.log(data);#} var data = JSON.parse(data); if(data["user"]){ //或者也可以用data.user $(".xxx").html("註冊成功"); window.location.href="/login/"; } else { console.log(data.msg_errors); //拿到的是所有的錯誤信息 $.each(data.msg_errors,function (i,v) { console.log(i,v); $span = $("<span>");//創建一個span標簽,方便提示錯誤信息的時候用 $span.addClass("pull-right").css("color","red"); //設置樣式居右並且字體顏色為紅色 $span.html(v[0]);//設置span裏面的字體 $("#id_"+i).after($span).parent().addClass("has-error");//吧span標簽放到每個input的後面顯示並且讓他的父親變紅,增加一個has-error的類 if (i=="__all__"){ $("#id_password_again").after($span) } }); } } }) }); //頭像預覽 $(".avatar_file").change(function () { var ele_file = $(this)[0].files[0]; //當前選中的文件 var reader = new FileReader(); reader.readAsDataURL(ele_file); //對應找到打開的url reader.onload=function () { {# 方式一#} $(".avatar_img").attr("src",this.result) ; //this.result是上面找到的url {# 方式二#} {# $(".avatar_img")[0].src=this.result; //設置圖片屬性#} } }) }) </script> </body> </html>
reg.css
.c1 { margin-right: 10px; } h2 { margin-top: 100px; margin-left: 280px; } .left{ position: relative; } .right{ width: 270px; height: 294px; position: absolute; top: 197px; left: 886px; } .registr_btn{ width: 100px; margin-left: 200px; } .avatar{ position: relative; width: 70px; height: 70px; } .avatar_img,.avatar_file{ position: absolute; width: 70px; height: 70px; top: 0; left: 46px; } .avatar_file{ opacity: 0; }
效果截圖
Django 【第十七篇】使用Form組件和Ajax實現用戶註冊