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>

浙公网安备 33010602011771号