BBS第二天之注册
注册渲染:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css"> <script src="/static/jquery-3.3.1.js"></script> <title>注册</title> <style> #myfile { display: none; } .error{ color:red; } </style> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <h1>注册</h1> <hr> <form id="myform" novalidate> {% csrf_token %} {% for field in reg_form %} <div class="form-group"> {# field.auto_id取出当前input框自动生成的id#} <label for="{{ field.auto_id }}">{{ field.label }}</label> {{ field }} <span class="error pull-right"></span> </div> {% endfor %} <div class="form-group"> <label for="myfile">头像 {# 把img标签放到label内 #} <img src="/static/img/default.png" height="80" width="80" id='my_img' style="margin-left: 10px"> </label> {#当input发生变化时,来把图片显示在img中#} <input type="file" id="myfile" accept="image/*"> </div> <input type="button" class="btn btn-primary" value="注册" id="id_submit"> </form> </div> </div> </div> </body> <script> //要用change事件 $("#myfile").change(function () { //取到文件对象 var myfile = $("#myfile")[0].files[0] //文件阅读器,生成一个文件阅读器对象 var filereader = new FileReader() //把文件读入该对象 filereader.readAsDataURL(myfile) //等图片完全读入filereader中,再进行操作 filereader.onload = function () { //filereader.result 文件内容,把文件内容放到src属性上 $("#my_img").attr('src', filereader.result) } }) $("#id_submit").click(function () { //ajax提交文件,得通过formdata对象 var formdata = new FormData() /*复杂方式 formdata.append('username',$("#id_username").val()) formdata.append('password',$("#id_password").val()) formdata.append('re_password',$("#re_password").val()) */ //取到form表单 console.log($("#myform").serializeArray()) var upload_data = $("#myform").serializeArray() //jq的循环:两个参数,第一个参数是要循环的对象,第二个参数传一个匿名函数 $.each(upload_data, function (index, obj) { //console.log(index) //console.log(obj)---{'name':'username','value':'lqz'} //这里添加的内容包括csrf的东西 formdata.append(obj.name, obj.value) }) //把csrf添加到formdata中 //取到csrf值得两种方式, //第一种:'{{ csrf_token }}' //第二种方式:jq取值:$("[name='csrfmiddlewaretoken']").val() //formdata.append('csrfmiddlewaretoken','{{ csrf_token }}') //formdata.append('csrfmiddlewaretoken',$("[name='csrfmiddlewaretoken']").val()) //手动把文件放到formdata中 formdata.append('myfile', $("#myfile")[0].files[0]) //提交ajax请求 $.ajax({ url: '/register/', type: 'post', //上传文件 processData: false, contentType: false, data: formdata, success: function (data) { //console.log(data) if(data.status==100){ //注册成功,跳转 location.href=data.url //location.href='/login/' }else { //console.log(data.msg) //清空错误信息 $("span.error").text("") $(".form-group").removeClass('has-error') //循环错误信息 $.each(data.msg,function (field,obj) { console.log(field) console.log(obj) //谁的错误,显示在谁的span中 //$("#id_"+field)取到有错误信息的input框,next取到下一个标签也就是span,在span标签中把错误信息写入 // $("#id_"+field).next().html(obj[0]) //$("#id_"+field).next().parent().addClass('has-error') //支持链式操作 var aa='#id_'+field alert(aa) $(aa).next().html(obj[0]).parent().addClass('has-error') if(field=='__all__'){ //当两次密码不一致的时候,在确认密码的span标签中渲染错误信息 $("#id_re_password").next().html(obj[0]) } //过3秒清掉错误信息 setTimeout(function () { $("span.error").text("") $(".form-group").removeClass('has-error') //清掉value的值 },3000) }) } } }) }) </script> </html>
form字段的创建及校验:
from django import forms from django.forms import widgets from app01 import models from django.core.exceptions import ValidationError class RegForm(forms.Form): username = forms.CharField(max_length=8, min_length=3, label='用户名', error_messages={'max_length': '用户名过长', 'min_length': '太短了', 'required': '该项必填'}, widget=widgets.TextInput(attrs={'class': 'form-control'})) password = forms.CharField(max_length=8, min_length=3, label='密码', error_messages={'max_length': '密码名过长', 'min_length': '太短了', 'required': '该项必填'}, widget=widgets.PasswordInput(attrs={'class': 'form-control'})) re_password = forms.CharField(max_length=8, min_length=3, label='确认密码', error_messages={'max_length': '确认密码过长', 'min_length': '太短了', 'required': '该项必填'}, widget=widgets.PasswordInput(attrs={'class': 'form-control'})) email = forms.EmailField(error_messages={'required': '该项必填', 'invalid': '格式错误'}, widget=widgets.EmailInput(attrs={'class': 'form-control'})) # 局部校验username字段 def clean_username(self): name = self.cleaned_data.get('username') user = models.UserInfo.objects.filter(username=name).first() if user: raise ValidationError('该用户已存在') else: return name # 全局校验两次密码是否一致 def clean(self): pwd = self.cleaned_data.get('password') re_pwd = self.cleaned_data.get('re_password') if not pwd == re_pwd: raise ValidationError('两次密码不一致') else: return self.cleaned_data
注册视图函数:
from app01.myforms import RegForm from app01 import models # Create your views here. def register(request): response_dic = {'status': 100, 'msg': None} reg_form = RegForm() if request.method == 'POST': # 生成一个RegForm对象,用于校验前台传过来的数据 reg_form = RegForm(request.POST) # 当reg_form.is_valid()是True,表示数据校验通过 if reg_form.is_valid(): # 取到清洗完的数据,内部带着re_re_password clean_data = reg_form.cleaned_data # 需要把re_password移除 clean_data.pop('re_password') # 要用create_user来创建用户 # {'username':'lqz','password':'123'} # 比较复杂一些 # name = clean_data.get('username') # pwd = clean_data.get('password') # eamil = clean_data.get('email') # # 取到文件对象 # myfile = request.FILES.get('myfile') # # 坑,myfile必须有值 # # 直接把文件对象赋值给avatar,它会自动保存到upload_to='avatar/' # if myfile: # models.UserInfo.objects.create_user(username=name, password=pwd, email=eamil, avatar=myfile) # else: # models.UserInfo.objects.create_user(username=name, password=pwd, email=eamil) # 简单一些 myfile = request.FILES.get('myfile') if myfile: clean_data['avatar'] = myfile models.UserInfo.objects.create_user(**clean_data) response_dic['msg'] = '注册成功' response_dic['url'] = '/login/' else: # 注册失败,返回错误信息,和状态码 response_dic['status'] = 101 response_dic['msg'] = reg_form.errors return JsonResponse(response_dic) return render(request, 'register.html', {'reg_form': reg_form})
效果图: