1、註冊相關的知識點css
一、Form組件html
咱們通常寫Form的時候都是把它寫在views視圖裏面,那麼他和咱們的視圖函數也不影響,咱們能夠吧它單另拿出來,在應用下面建一個forms.py的文件來存放python
二、局部鉤子函數jquery
# 局部鉤子函數 def clean_username(self): username = self.cleaned_data.get("username") valid = models.UserInfo.objects.filter(username=username).first() if valid: raise ValidationError("用戶名已存在!") return username
三、全局鉤子函數ajax
# 全局鉤子函數:驗證兩次密碼是否一致 def clean(self): if self.cleaned_data.get("password") == self.cleaned_data("password_again"): return self.cleaned_data else: raise ValidationError("兩次密碼不一致")
四、 jQuery的屬性操做相關的數據庫
attr: 一個參數是獲取屬性的值,兩個參數是設置屬性值 removeAttr(屬性名): 刪除屬性值 prop: 適應於屬性的返回值是布爾類型的(單選,反選,取消的例子) removePorp: 刪除屬性的值
五、循環的兩種方式json
$.each(數組/對象,function(i,v){}) $("div").each(function(i,v){})
六、css中的三種隱藏:bootstrap
一、display:none 隱藏全部內容 二、visibility:hidden 隱藏內容 三、overflow:hidden 隱藏溢出內容 三者都是用來隱藏的 區別在於: visibility:雖然隱藏了,可是被隱藏的內容依然佔據這空間,這段隱藏了的內容卻保留空間的位置會在網頁中顯示空白 display:隱藏了不佔用空間
七、提交二進制數據用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]);
加上:cookie
contentType:false processData:false
八、能夠用下面的方法判斷是什麼請求
if request.ajax(): # 若是ajax請求 if request.method=="POST" # 若是是post請求
九、上傳文件有一個固定的配置參數media
步驟以下:
- 首先在settings中配置:
# 與用戶上傳相關的配置 MEDIA_ROOT = os.path.join(BASE_DIR, "media") # 具體路徑 MEDIA_URL = "/media/" # 別名
- 在路由裏面配置:
# media配置: re_path(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">
圖片上傳成功保存的目錄
十、頭像圖片預覽
// 頭像預覽 $("#avatar").change(function () { var ele_file = $(this)[0].files[0]; // 當前選中的文件 // 獲取文件對象的路徑 var reader = new FileReader(); reader.readAsDataURL(ele_file); // 對應找到打開的url console.log(ele_file) // 修改img的src屬性,src=文件對象的路徑 reader.onload = function () { {# 方式一 #} $(".avatar_img").attr("src", this.result); // this.result上上面找到的url {# 方式二 #} {# $(".avatar_img")[0].src=this.result; //設置圖片屬性#} } })
十一、form自動生成的錯誤信息
當你定義了全局鉤子的時候,並且正好出現你的那個全局鉤子函數中的錯(好比兩次密碼輸入不一致),這樣你打印錯誤信息的時候
會有一個__all__對象,這個就是你設置的全局鉤子生成的。
因此還要單獨判斷一下,如今全局鉤子只有一個,你能夠這樣判斷,可是,當全局鉤子多的時候就得一個一個分開來判斷
if (i=="__all__"){ $("#id_password_again").after($span) }
2、具體實現註冊操做
url.py
url(r'^register/$', views.register), # media配置: re_path(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}) # return render(request, "reg.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") models.UserInfo.objects.create_user(username=username, password=password, tel=tel, avatar_img=avatar_img) regresponse["user"] = username else: regresponse["msg_errors"] = form.errors return HttpResponse(json.dumps(regresponse))
forms.py
class RegisterForm(Form): username = fields.CharField( required=True, max_length=16, min_length=3, error_messages={ "required": "用戶名不能爲空!", "max_length": "長度不能大於16", "max_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", "max_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", "max_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(self): if self.cleaned_data.get("password") == self.cleaned_data("password_again"): return self.cleaned_data else: raise ValidationError("兩次密碼不一致")
register.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.css"> 7 <link rel="stylesheet" href="/static/css/res.css"> 8 <script src="/static/js/jquery-3.3.1.js"></script> 9 <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script> 10 <script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.js"></script> 11 12 </head> 13 <body> 14 {#導航條#} 15 <nav class="navbar navbar-inverse navbar-fixed-top"> 16 <div class="container pull-left"> 17 <!-- Brand and toggle get grouped for better mobile display --> 18 <div class="navbar-header"> 19 <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" 20 data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> 21 <span class="sr-only">Toggle navigation</span> 22 <span class="icon-bar"></span> 23 <span class="icon-bar"></span> 24 <span class="icon-bar"></span> 25 </button> 26 <a class="navbar-brand" href="#">博客園</a> 27 </div> 28 29 <!-- Collect the nav links, forms, and other content for toggling --> 30 <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> 31 <ul class="nav navbar-nav"> 32 <li class="active c1"><a href="#">首頁 <span class="sr-only">(current)</span></a></li> 33 <li class="active c1"><a href="#">登陸</a></li> 34 <li class="active c1"><a href="#">註冊</a></li> 35 <li class="active c1"><a href="#">幫助</a></li> 36 </ul> 37 </div><!-- /.navbar-collapse --> 38 </div><!-- /.container-fluid --> 39 </nav> 40 <h2>註冊新用戶</h2> 41 <hr> 42 <div class="container"> 43 <div class="row left"> 44 <div class="col-md-6 col-md-offset-1"> 45 <form action="/register/" method="post" novalidate enctype="multipart/form-data"> 46 {% csrf_token %} 47 <div class="form-group"> 48 <label for="username" class="control-label">用戶名:</label> 49 <div>{{ form.username }}<span></span></div> 50 </div> 51 <div class="form-group"> 52 <label for="password" class="control-label">密碼:</label> 53 <div>{{ form.password }}<span></span></div> 54 </div> 55 <div class="form-group"> 56 <label for="password" class="control-label">確認密碼:</label> 57 <div>{{ form.password_again }}<span></span></div> 58 </div> 59 <div class="form-group"> 60 <label for="Email" class="control-label">郵箱:</label> 61 <div>{{ form.email }}<span></span></div> 62 </div> 63 <div class="form-group"> 64 <label for="tel" class="control-label">手機號碼:</label> 65 <div>{{ form.tel }}<span></span></div> 66 </div> 67 <div class="form-group"> 68 <label for="avatar" class="control-label">頭像:</label> 69 <img src="/static/image/default.png" alt="" class="avatar_img"> 70 <input type="file" id="avatar" name="avatar_file" class="avatar_file"> 71 </div> 72 <button type="button" class="btn btn-primary registr_btn">註冊</button><span class="error"></span> 73 </form> 74 </div> 75 </div> 76 <div class="right"> 77 {# <img src="/static/image/lufei.jpg" alt="">#} 78 </div> 79 80 </div> 81 <script> 82 $(function () { 83 // 給註冊按鈕添加事件 84 $(".registr_btn").click(function () { 85 var formData = new FormData(); 86 formData.append("username", $("#id_username").val()); 87 formData.append("email", $("#id_email").val()); 88 formData.append("tel", $("#id_tel").val()); 89 formData.append("password", $("#id_password").val()); 90 formData.append("password_again", $("#id_password_again").val()); 91 formData.append("avatar_img", $("#avatar")[0].files[0]); 92 93 94 $(".pull-right").html(""); 95 $(".pull-right").parent().removeClass("has-error"); 96 $.ajax({ 97 url:"/register/", 98 type: "post", 99 headers: {"X-CSRFToken": $.cookie('csrftoken')}, 100 data:formData, 101 contentType:false, 102 processData:false, 103 success:function (data) { 104 105 var data = JSON.parse(data); 106 if (data["user"]){ 107 $(".error").html("註冊成功") 108 window.location.href="/login/"; 109 110 } 111 else { 112 // 先清除錯誤信息 113 114 console.log(data.msg_errors); // 拿到的是全部的錯誤信息 115 $.each(data.msg_errors, function (field, error_list) { 116 console.log(field, error_list); 117 $span = $("<span>"); 118 $span.addClass("pull-right").css("color", "red"); 119 120 $span.html(error_list[0]); 121 $("#id_" + field).after($span).parent().addClass("has-error"); 122 // 錯誤信息5秒消失 123 setTimeout(function () { 124 $(".pull-right").text("") 125 126 }, 5000); 127 128 if (field=="__all__"){ 129 $("#id_password_again").after($span); 130 } 131 132 133 134 135 136 137 138 139 }); 140 } 141 142 } 143 }) 144 }); 145 146 // 頭像預覽 147 $("#avatar").change(function () { 148 var ele_file = $(this)[0].files[0]; // 當前選中的文件 149 // 獲取文件對象的路徑 150 var reader = new FileReader(); 151 reader.readAsDataURL(ele_file); // 對應找到打開的url 152 console.log(ele_file) 153 // 修改img的src屬性,src=文件對象的路徑 154 reader.onload = function () { 155 {# 方式一 #} 156 $(".avatar_img").attr("src", this.result); // this.result上上面找到的url 157 {# 方式二 #} 158 {# $(".avatar_img")[0].src=this.result; //設置圖片屬性#} 159 160 } 161 162 }) 163 164 165 166 }) 167 </script> 168 </body> 169 </html>
reg.css
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 display: none; 25 } 26 .avatar_img,.avatar_file{ 27 position: absolute; 28 width: 60px; 29 height: 60px; 30 31 left: 60px; 32 } 33 .avatar_file{ 34 opacity: 0; 35 } 36 37 .error { 38 color: red; 39 margin-left: 10px; 40 }
效果截圖