Django项目 基于form的注册示例/头像图片的预览功能/form校验功能/ajax提交注册数据并显示错误信息

新增:forms.py文件

 1 """
 2 bbs用到的form类
 3 """
 4 
 5 from django import forms
 6 from django.core.exceptions import ValidationError
 7 
 8 
 9 # 定义一个注册的form类
10 class RegForm(forms.Form):  # 继承forms.Form
11     username = forms.CharField(
12         max_length=16,  # 用户名最长 16位
13         label="用户名",
14         error_messages={
15             "max_length": "用户名最长16位",
16             "required": "用户名不能为空",
17         },
18         widget=forms.widgets.TextInput(  # 生成的input标签添加class
19             attrs={"class": "form-control"},  # form-control一般用于置于div中的标签元素,为了让控件在各种表单风格中样式不出错,需要添加类名“form-control
20         )
21     )
22 
23     password = forms.CharField(
24         min_length=6,
25         label="密码",
26         widget=forms.widgets.PasswordInput(  # widget:输入框的类型,以及样式自定义
27             attrs={"class": "form-control"},  # attrs:用来存放html标签的属性,以字典的形式,如设置class属性:attrs = {'class' = 'c1  c2'},
28             render_value=True,  # 如果render_value = True会将出错数据跟错误信息返回,False只返回错误信息
29         ),
30             error_messages={
31                 "min_length": "密码至少要6位!",
32                 "required": "密码不能为空",
33             }
34         )
35 
36     re_password = forms.CharField(
37         min_length=6,
38         label="确认密码",
39         widget=forms.widgets.PasswordInput(
40             attrs={"class": "form-control"},
41             render_value=True,  # 密码错误后不消失
42         ),
43         error_messages={
44             "min_length": "确认密码至少要6位!",
45             "required": "确认密码不能为空",
46         }
47     )
48 
49     email = forms.EmailField(
50         label="邮箱",
51         widget=forms.widgets.EmailInput(
52             attrs={"class": "form-control"},
53 
54         ),
55         error_messages={
56             "invalid": "邮箱格式不正确!",
57             "required": "邮箱不能为空",
58         }
59     )
60 
61     # 重写全局的钩子函数,对确认密码做校验
62 
63     def clean(self):
64         password = self.cleaned_data.get("password")
65         re_password = self.cleaned_data.get("re_password")
66 
67         if re_password and re_password != password:
68             self.add_error("re_password", ValidationError("两次密码不一致"))
69 
70         else:
71             return self.cleaned_data

路由:urls.py文件

 1 from django.contrib import admin
 2 from django.urls import path
 3 from boo import views
 4 
 5 urlpatterns = [
 6     path('admin/', admin.site.urls),
 7 
 8     path('login/', views.login),#登录
 9     path('index/', views.index),
10     path('logout/', views.logout),#退出登录
11     path('reg/', views.register), #注册
12     path('upload/',views.upload)   #文件上传

视图:views.py文件

 1 from django.shortcuts import render, redirect, HttpResponse
 2 # Create your views here.
 3 from django.contrib import auth
 4 from django.contrib.auth.decorators import login_required
 5 from django.views.decorators.csrf import csrf_exempt    #导入以后下方调用csrf_exempt
 6 from boo import forms
 7 from django.http import JsonResponse
 8 from boo import models
 9 
10 # 注册的视图函数
11 def register(request):
12     if request.method == "POST":
13         ret = {"status": 0, "msg": ""}
14         form_obj = forms.RegForm(request.POST)
15         print(request.POST)
16         # 帮我做校验
17         if form_obj.is_valid():
18             # 校验通过,去数据库创建一个新的用户
19             form_obj.cleaned_data.pop("re_password")  #确认密码字段
20             avatar_img = request.FILES.get("avatar")  #获取头像
21             models.UserInfo.objects.create_user(**form_obj.cleaned_data, avatar=avatar_img)  #创建新用户
22             ret["msg"] = "/index/"
23             return JsonResponse(ret)
24         else:
25             print(form_obj.errors)
26             ret["status"] = 1
27             ret["msg"] = form_obj.errors
28             print(ret)
29             print("=" * 120)
30             return JsonResponse(ret)
31     # 生成一个form对象
32     form_obj = forms.RegForm()
33     print(form_obj.fields)
34     return render(request, "register.html", {"form_obj": form_obj})

前端:register.html

  1 <!DOCTYPE html>
  2 <html lang="en">
  3 <head>
  4     <meta charset="UTF-8">
  5     <title>欢迎注册</title>
  6     <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
  7     <link rel="stylesheet" href="/static/mystyle.css">
  8 </head>
  9 <body>
 10 
 11 <div class="container">
 12     <div class="row">
 13         <div class="col-md-6 col-md-offset-3">
 14             <form novalidate action="/reg/" method="post" class="form-horizontal reg-form" enctype="multipart/form-data">
 15                 {% csrf_token %}
 16 {#                获取form_obj的三种方式--方式1 一个一个取值#}
 17 {#                {{ form_obj.username.label }}#}
 18 {#                {{  form_obj.username }}#}
 19 {#                {{ form_obj.password.label }}#}
 20 {#                {{  form_obj.password }}#}
 21 {#             获取form_obj的三种方式--方式2  循环取值   #}
 22 {#                {% for field in form_obj %}#}
 23 {#                    {{ field.label }}#}
 24 {#                    {{ field }}#}
 25 {#                {% endfor %}#}
 26                 <div class="form-group">
 27                     <label for="{{ form_obj.username.id_for_label }}"
 28 {#                           获取焦点  点击用户名自动校准到输入框#}
 29                            class="col-sm-2 control-label">{{ form_obj.username.label }}</label>
 30                     <div class="col-sm-8">
 31                         {{ form_obj.username }}
 32                         <span class="help-block">{{ form_obj.username.errors.0 }}</span>
 33                     </div>
 34                 </div>
 35 
 36                 <div class="form-group">
 37                     <label for="{{ form_obj.password.id_for_label }}"
 38                            class="col-sm-2 control-label">{{ form_obj.password.label }}</label>
 39                     <div class="col-sm-8">
 40                         {{ form_obj.password }}
 41                         <span class="help-block">{{ form_obj.password.errors.0 }}</span>
 42                     </div>
 43                 </div>
 44 
 45                 <div class="form-group">
 46                     <label for="{{ form_obj.re_password.id_for_label }}"
 47                            class="col-sm-2 control-label">{{ form_obj.re_password.label }}</label>
 48                     <div class="col-sm-8">
 49                         {{ form_obj.re_password }}
 50                         <span class="help-block">{{ form_obj.re_password.errors.0 }}</span>
 51                     </div>
 52                 </div>
 53 
 54                 <div class="form-group">
 55                     <label for="{{ form_obj.email.id_for_label }}"
 56                            class="col-sm-2 control-label">{{ form_obj.email.label }}</label>
 57                     <div class="col-sm-8">
 58                         {{ form_obj.email }}
 59                         <span class="help-block">{{ form_obj.email.errors.0 }}</span>
 60                     </div>
 61                 </div>
 62 
 63                 <div class="form-group">
 64                     <label
 65                             class="col-sm-2 control-label">头像</label>
 66                     <div class="col-sm-8">
 67 {#                        把点击头像和上传文件通过id相关联 点击头像就是选择上传文件 style=”display:none“ 选择文件按钮隐藏#}
 68                         <label for="id_avatar"><img id="avatar-img" src="/static/img/default.png" alt=""></label>
 69                         <input accept="image/*" type="file" name="avatar" id="id_avatar" style="display: none">
 70                         <span class="help-block"></span>
 71                     </div>
 72                 </div>
 73 
 74                 <div class="form-group">
 75                     <div class="col-sm-offset-2 col-sm-10">
 76                         <button type="button" class="btn btn-success" id="reg-submit">注册</button>
 77                     </div>
 78                 </div>
 79             </form>
 80         </div>
 81     </div>
 82 </div>
 83 
 84 
 85 <script src="/static/jquery-3.3.1.js"></script>
 86 <script src="/static/bootstrap/js/bootstrap.min.js"></script>
 87 <script>
 88     // 找到头像的input标签绑定change事件
 89     $("#id_avatar").change(function () {
 90         // 1. 创建一个读取文件的对象
 91         var fileReader = new FileReader();
 92         // 取到当前选中的头像文件
 93         // console.log(this.files[0]);
 94         // 读取你选中的那个文件
 95         fileReader.readAsDataURL(this.files[0]);  // 读取文件是需要时间的
 96         fileReader.onload = function () {
 97             // 2. 等上一步读完文件之后才 把图片加载到img标签中
 98             $("#avatar-img").attr("src", fileReader.result);
 99         };
100     });
101     // AJAX提交注册的数据
102     $("#reg-submit").click(function () {
103         // 取到用户填写的注册数据,向后端发送AJAX请求
104         var formData = new FormData();
105         formData.append("username", $("#id_username").val());
106         formData.append("password", $("#id_password").val());
107         formData.append("re_password", $("#id_re_password").val());
108         formData.append("email", $("#id_email").val());
109         formData.append("avatar", $("#id_avatar")[0].files[0]);
110         formData.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val());
111 
112         $.ajax({
113             url: "/reg/",
114             type: "post",
115             {#ajax传带文件的数据必须有下面两行#}
116             processData: false,
117             contentType: false,
118             data: formData,
119             success:function (data) {
120                 if (data.status){
121                     // 有错误就展示错误
122                     // console.log(data.msg);
123                     // 将报错信息填写到页面上   循环报错信息
124                     $.each(data.msg, function (k,v) {
125                         // console.log("id_"+k, v[0]);
126                         // console.log($("#id_"+k));
127                         $("#id_"+k).next("span").text(v[0]).parent().parent().addClass("has-error");
128                     })
129 
130                 }else {
131                     // 没有错误就跳转到指定页面
132                     location.href = data.msg;
133                 }
134             }
135         })
136     });
137 
138     // 将所有的input框绑定获取焦点的事件,将所有的错误信息清空
139     $("form input").focus(function () {
140         $(this).next().text("").parent().parent().removeClass("has-error");
141     })
142 </script>
143 </body>
144 </html>

 

posted @ 2022-09-25 22:22  张丶先森  阅读(45)  评论(0)    收藏  举报