Web框架開發-Form組件和ajax實現註冊

 

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))
views.py

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("兩次密碼不一致")
forms.py

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>
register.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 }
res.css

效果截圖

相關文章
相關標籤/搜索