本次注册时的需求:
1.用ajax提交数据
2.用form表单渲染数据
3.上传头像是二进制数据用formData
4.上传头像需要专门地方存放:需要配置Media。
5.上传头像需要预览.
首先配置media:
a.setting里面的配置
MEDIA_ROOT=os.path.join(BASE_DIR,"blog","media","uploads") MEDIA_URL="/media/"
b.全局的urls里面的配置(因为系统没有配置的server)
# media 配置 url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT})
首先先写form表单:(钩子函数写在后面)
from django import forms from django.forms import widgets,ValidationError from blog import models class RegForm(forms.Form):#定义 username=forms.CharField( max_length=12, min_length=5, required=True, error_messages={ "required":"不能为空", }, widget=widgets.TextInput(attrs={"class":"form-control","placeholder":"username"})) password=forms.CharField( min_length=6, widget=widgets.PasswordInput( attrs={"class": "form-control", "placeholder": "password"} )) repeat_pwd=forms.CharField( min_length=6,widget=widgets.PasswordInput( attrs={"class": "form-control", "placeholder": "repeat_pwd"} )) email=forms.EmailField(widget=widgets.EmailInput( attrs={"class": "form-control", "placeholder": "email"} )) def clean_username(self):#定义局部钩子函数form表单里的数据都在cleaned_data ret=models.UserInfo.objects.filter(username=self.cleaned_data.get("username")) if not ret: return self.cleaned_data.get("username")#返回的都是自己的数据 else: raise ValidationError("用户名已注册") def clean_password(self): data=self.cleaned_data.get("password") if not data.isdigit(): return self.cleaned_data.get("password") else: raise ValidationError("密码不能全是数字") def clean_validCode(self):#定义验证验证码的钩子因为没有request需要自己的定义一个 if self.cleaned_data.get("validCode")== self.request.session.get("validCode"): return self.cleaned_data.get("validCode") else: raise ValidationError("验证码错误") def clean(self): if self.cleaned_data.get("password") == self.cleaned_data.get("repeat_pwd"): return self.cleaned_data else: raise ValidationError("两次密码不一致") def __init__(self,request,*args,**kwargs):#这是为验证验证码自定义的一个 super().__init__(*args,**kwargs)#继承父辈 self.request=request
Views视图里的注册函数:
def reg(request): if request.is_ajax(): form_obj=forms.RegForm(request,request.POST) regResponse={"user":None,"errorsList":None}#这个是给ajax返回数据用的 if form_obj.is_valid():#判断是否通过钩子函数 username=form_obj.cleaned_data["username"] password=form_obj.cleaned_data["password"] email=form_obj.cleaned_data.get("email") avatar_img=request.FILES.get("avatar_img") if avatar_img:#如果拿到上传的头像就用上传的 user_obj=models.UserInfo.objects.create_user(username=username,password=password,email=email,avatar=avatar_img,nickname=username) else:#否则就用默认的 user_obj=models.UserInfo.objects.create_user(username=username,password=password,email=email,nickname=username) print(user_obj.avatar,"......") regResponse["user"]=user_obj.username else: regResponse["errorsList"]=form_obj.errors#所有错误的数据都放在errors里面 import json return HttpResponse(json.dumps(regResponse)) form_obj=forms.RegForm(request)#在没有数据时渲染页面,定义form时用(form.From)这里就要用request return render(request,"reg.html",{"form_obj":form_obj})
reg.tml页面:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> <script src="/static/dist/js/jquery-3.1.1.js"></script> <script src="/static/dist/js/bootstrap.js"></script> <link rel="stylesheet" href="/static/dist/css/bootstrap.css"> <link rel="stylesheet" href="/static/css/reg.css"> <script src="/static/js/jquery.cookie.js"></script> </head> <body> <div class="container"> <div class="row"> <div class="col-md-5 col-md-offset-3"> <form> {% csrf_token %}<!--用form表单一定要用这个--> <div class="form-group"> <label for="username">用户名</label> {{ form_obj.username }} </div> <div class="form-group"> <label for="password">密码</label> {{ form_obj.password }} </div> <div class="form-group"> <label for="password">确认密码</label> {{ form_obj.repeat_pwd }} </div> <div class="form-group"> <label for="email">邮箱</label> {{ form_obj.email }} </div> <div class="form-group avatar"> <label for="avatar">头像</label> <img src="/static/img/default.png" alt="" id="avatar_img"><!--这里是和inpu放在一起通过css控制--> <input type="file" class="form-control" id="avatar_file" ><!--这是上传头像的--> </div> <input type="button" value="submit" class="btn btn-primary" id="subBtn"><span class="error"></span> </form> </div> </div> </div> <script> // 头像预览 $("#avatar_file").change(function () { var ele_file=$(this)[0].files[0]; //this.files var reader=new FileReader(); reader.readAsDataURL(ele_file); reader.onload=function () { $("#avatar_img")[0].src=this.result } }); $("#subBtn").click(function () { <!--用formData上传二进制数据--> var formdata=new FormData(); formdata.append("username",$("#id_username").val()); formdata.append("password",$("#id_password").val()); formdata.append("repeat_pwd",$("#id_repeat_pwd").val()); formdata.append("email",$("#id_email").val()); formdata.append("avatar_img",$("#avatar_file")[0].files[0]); $(".pull-right").html(""); $(".pull-right").parent().removeClass("has-error"); $.ajax({ url:"/reg/", type:'POST', data:formdata, contentType:false, processData:false, headers:{"X-CSRFToken":$.cookie('csrftoken')}, success:function (data) { {# console.log(data);#} var data=JSON.parse(data); if (data.user){ location.href="/login/" } else { console.log(data.errorsList); $.each(data.errorsList,function (i,j) { console.log(i,j); $span=$("<span>"); $span.addClass("pull-right").css("color","red"); $span.html(j[0]); $("#id_"+i).after($span).parent().addClass("has-error") console.log($("#id_"+i).next($span)) if (i=="__all__"){<!--这是用来判断全局钩子的--> $("#id_repeat_pwd").after($span) } }) } } }) }) </script> </body> </html>