1.注册页面头像预览
方式一:
var obj = $(this)[0] jQuery对象转化成DOM对象
var obj = $(this)[0].files
var obj = $(this)[0].files[0]; 获取上传文件的文件对象
方式二:
window.URL.createObjectURL
function () { [native code] }如果上传图片到内存立即释放,会出现报错(window.URL.revokeObjectURL(v);)
function bindAvatar2() { $('#imgFile').change(function () { var obj = $(this)[0].files[0]; //ajax发送到后台,并获取路径 //img.src = 获取路径 var v = window.URL.createObjectURL(obj); $('#previewImg').attr('src',v); window.URL.revokeObjectURL(v); }) }
function bindAvatar2() { $('#imgFile').change(function () { var obj = $(this)[0].files[0]; //ajax发送到后台,并获取路径 //img.src = 获取路径 var v = window.URL.createObjectURL(obj); $('#previewImg').attr('src',v); $('#previewImg').load(function () { window.URL.revokeObjectURL(v); }); })}
加载完成之后释放就能正常显示了
方式三:onload事件
$(function () { bindAvatar3(); }); /* 本地ajax上传 */ function bindAvatar3() { $('#imgFile').change(function () { var obj = $(this)[0].files[0]; //ajax发送到后台,并获取路径 //img.src = 获取路径 var reader = new FileReader(); reader.readAsDataURL(obj); reader.onload = function(){ $('#previewImg').attr('src',this.result); } }) }
window.URL.createObjectURL
function () { [native code] }做if判断(if,else if,else) 用方式二和方式三兼容性较差,但是都是上传图片到内存,减轻图片上传到服务器的压力,方式一兼容性较好。
方式四:FormData上传:
2.注册页面
定义一个RegisterForm类和register函数:
- Form组件中通过构造方法可以封装自己想要的值from django.forms import Formfrom django.forms import fieldsfrom django.forms import widgetsfrom django.core.exceptions import ValidationErrorfrom django.core.validators import RegexValidatorfrom app01 import modelsclass RegisterForm(Form): username = fields.CharField( required=True, widget=widgets.TextInput( attrs={ 'class':'form-control','placeholder':'用户名为6-10个字符'} ), min_length=6, max_length=10, strip=True, error_messages={ 'required': '用户名不能为空', 'min_length':'用户名至少为6个字符', 'max_length':'用户名不超过10个字符', }, ) password = fields.CharField( required=True, widget=widgets.PasswordInput( attrs={ 'class':'form-control','placeholder':'密码为8-12个字符'} ), min_length=8, max_length=12, strip=True, validators=[ RegexValidator(r'((?=.*\d))^.{8,12}$','必须包含数字'), RegexValidator(r'((?=.*[a-zA-Z]))^.{8,12}','必须包含字母'), # RegexValidator(r'((?=.*[^a-zA-Z0-9]))^.{8,12}','必须包含特殊字符'), # RegexValidator(r'^.(\s){8,12}','必须包含空格'), ],#用于对密码的正则验证 error_messages={ 'required': '密码不能为空', 'min_length':'密码不能少于8个字符', 'max_length':'密码最多为12个字符!', } ) password_again = fields.CharField( required=True, widget=widgets.PasswordInput( attrs={ 'class':'form-control','placeholder':'密码为8-12个字符'} ), min_length=8, max_length=12, strip=True, error_messages={ 'required':'请再次输入密码!',} ) nickname = fields.CharField( required=True, widget=widgets.TextInput( attrs={ 'class':'form-control','placeholder':'请输入昵称'} ) ) email = fields.EmailField( required=True, widget=widgets.TextInput(attrs={ 'class':'form-control','placeholder':'请输入邮箱'}), # strip=True, # error_messages={ 'required':'邮箱不能为空','invalid':'请输入正确的邮箱格式'}, ) avatar = fields.FileField(widget=widgets.FileInput(attrs={ 'id':'imgFile','class':'f1'})) code = fields.CharField(widget=widgets.TextInput(attrs={ 'class':'form-control','placeholder':'请输入验证码'})) def clean_username(self): #对于username扩展验证,查看是否存在 username = self.cleaned_data['username'] users = models.UserInfo.objects.filter(username=username).count() if users:#如果用户名已存在 raise ValidationError('用户名已经存在!') return username def clean_email(self): #对于email的扩展验证,查看是否存在 email = self.cleaned_data['email'] email_count = models.UserInfo.objects.filter(email=email).count() if email_count: raise ValidationError('邮箱已经存在!') return email # def _clean_password(self):#验证两次输入密码是否一致 # password1 = self.cleaned_data['password'] # password2 = self.cleaned_data['password_again'] # if password1 and password2: # if password1 != password2: # raise ValidationError('您两次输入的密码不一致') def __init__(self,request,*args,**kwargs):#构造方法,传request参数 super(RegisterForm,self).__init__(*args,**kwargs)#完成原有form功能以外 self.request = request#再封装一个request def clean_code(self): input_code = self.cleaned_data['code'] session_code = self.request.session.get('code')#session取验证码 if input_code.upper() == session_code.upper():#验证相等时 return input_code# raise ValidationError('验证码错误') def clean(self): # 验证两次输入密码是否一致 p1 = self.cleaned_data.get('password') p2 = self.cleaned_data.get('password_again') if p1 == p2: # return self.cleaned_data return None # else: # raise ValidationError('密码不一致') self.add_error("password_again",ValidationError('密码不一致')) #在页面的指定字段添加错误信息 """ Django源码添加错误信息 # except ValidationError as e: # self.add_error(name, e) """ # def clean(self): # #基于form对象的验证,字段全部验证通过会调用clean函数验证 # self._clean_password()#调用函数 # p1 = self.cleaned_data['password'] # p2 = self.cleaned_data['password_again'] # return p2
def register(request): """ 用户注册 :param request: :return: """ if request.method == "GET": obj = RegisterForm(request) return render(request,'register.html',{ 'obj':obj}) else: #验证码 obj = RegisterForm(request,request.POST,request.FILES) if obj.is_valid(): pass else: # print(obj.errors['__all__']) # print(obj.errors[NON_FIELD_ERRORS]) """
- 密码不一致
- 密码不一致
注册页面 用户注册
首先定义构造方法,使后端可以直接通过session取值,省去很多麻烦 def __init__(self,request,*args,**kwargs):#构造方法,传request参数 super(RegisterForm,self).__init__(*args,**kwargs)#完成原有form功能以外 self.request = request#再封装一个request
def register(request): """ 用户注册 :param request: :return: """ if request.method == "GET": obj = RegisterForm(request) return render(request,'register.html',{'obj':obj}) else: #验证码 obj = RegisterForm(request,request.POST,request.FILES) #这里相应传一个request参数 if obj.is_valid(): pass else: # print(obj.errors['__all__']) # print(obj.errors[NON_FIELD_ERRORS]) """
- 密码不一致
- 密码不一致
在RegisterForm类中自定义clean_code函数 1.显示验证码错误信息
def clean_code(self): input_code = self.cleaned_data['code'] session_code = self.request.session.get('code')#session取验证码 if input_code.upper() == session_code.upper():#验证相等时 return input_code# raise ValidationError('验证码错误') 2.验证密码是否一致
def clean(self): # 验证两次输入密码是否一致 p1 = self.cleaned_data.get('password') p2 = self.cleaned_data.get('password_again') if p1 == p2: # return self.cleaned_data return None # else: # raise ValidationError('密码不一致') self.add_error("password_again",ValidationError('密码不一致'))
前端HTML获取错误信息{ { obj.non_field_errors }}
class RegisterForm(Form): username = fields.CharField( widget=widgets.TextInput(attrs={ 'class':'form-control'}) ) password = fields.CharField( widget=widgets.PasswordInput(attrs={ 'class':'form-control'}) ) password2 = fields.CharField( widget=widgets.PasswordInput(attrs={ 'class':'form-control'}) ) avatar = fields.FileField(widget=widgets.FileInput(attrs={ 'id':"imgSelect",'class':"f1" })) code = fields.CharField( widget=widgets.TextInput(attrs={ 'class':'form-control'}) ) def __init__(self,request,*args,**kwargs): super(RegisterForm,self).__init__(*args,**kwargs) self.request = request
- 对于Form组件错误信息
{ __all__: [错误1,错误2] user: [错误1,错误2] password: [错误1,错误2] } # 获取整体错误信息 - 后台 print(obj.errors['__all__']) print(obj.errors[NON_FIELD_ERRORS]) - 模板 { { obj.non_field_errors }}Django源码关于form组件验证的流程: is_valid()-->self.errors-->self.full_clean()-->{self._clean_fields() self._clean_form() self._post_clean()}
from django.core.exceptions import NON_FIELD_ERRORS--->NON_FIELD_ERRORS = '__all__'
按照源码添加错误信息
except ValidationError as e:self.add_error(name, e)self.add_error('字段名称',错误异常对象)3.点击更换验证码
$('#i1').attr('src','/check_code/??')
添加一个onchange事件
function changeCode(ths) { ths.src = ths.src + "?"; }