今日学习内容
创建一个文件关于forms的校验代码。
from django import forms from django.forms import widgets from django.core.exceptions import ValidationError from blog.models import UserInfo # d导入模块:相对导入和绝对导入 class RegisterForm(forms.Form): # 用户名 密码 确认密码 邮箱 username = forms.CharField(max_length=8, min_length=3, required=True, label='用户名', error_messages={ 'max_length': '用户名过长', 'min_length': '用户名过短', 'required': '这个必填哦!', }, widget=widgets.TextInput(attrs={'class': 'form-control'})) password = forms.CharField(max_length=8, min_length=3, required=True, 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, required=True, label='确认密码', error_messages={ 'max_length': '用户名过长', 'min_length': '用户名过短', 'required': '这个必填哦!', }, widget=widgets.PasswordInput(attrs={'class': 'form-control'})) email = forms.EmailField(label='邮箱', widget=widgets.EmailInput(attrs={'class': 'form-control'})) # 局部钩子校验 def clean_username(self): username = self.cleaned_data.get('username') # 方案一: user = UserInfo.objects.filter(username=username).first() if user: #用户已存在,不合理 raise ValidationError('用户已存在') else: #将校验后的用户返回出去 return username # 方案二: # try: # UserInfo.objects.get(username=username) # 有且只有一条才行,否则就抛出异常。 # raise ValidationError('用户已存在!') # except Exception as e: # return username #这是一个与问题的代码。 # 全局钩子校验 def clean(self): password = self.cleaned_data.get('password') re_password = self.cleaned_data.get('re_password') if password == re_password: # 如果合理,则返回结果 return self.cleaned_data else: # 不合理,则主动抛出异常 raise ValidationError('两次密码不一致!')
# bootstrap 搭建 settings.py 中加入 static STATIC_URL = '/static/' STATICFILES_DIRS=[ os.path.join(BASE_DIR, 'static') ] 把bootstrap的静态资源copy到static文件夹下。 #新建模板文件 register.html
<body> <div> <div class="container-fluid"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <h1 class="text-center">注册功能</h1> <form id="id_form"> {# 没写这串代码会出现403权限错误#} {% csrf_token %} {% for item in form %} <div class="form-group"> <label for="{{ item.id_for_label }}">{{ item.label }}</label> {{ item }} <span class="pull-right text-danger "></span> </div> {% endfor %} <div calss="form-group"> <label for="id_file">头像 <img src="/static/img/default.png" alt="" id="id_img" height="80px" width="80px" style="margin-left: 10px"> </label> <input type="file" id="id_file" accept="image/*" style="display: none"> </div> <div class="form-group text-center"> {#如果input类型type为submit或者button标签,或者form表单中,如果点提交,触发form的提交,如果写了ajax提交,会触发两次提交#} <input type="button" value="注册" class="btn btn-success" id="id_submit"> <span class="text-danger error"></span> </div> </form> </div> </div> </div> </div> </body>
1.首先读文件,然后将读取到文件的阅读器将其放置在标签上面。 $("#id_file").change(function () { // 把当前图片,放到img标签中 // 把图片地址放到img标签上,标签就显示了图片 //$("#id_img")[0].src='https://tva1.sinaimg.cn/large/00831rSTly1gd1u0jw182j30u00u043b.jpg' // 1 id_file这个标签的图片读出来,借助于文件阅读器,js提供的一个类 var reader = new FileReader() // 2 拿到文件对象,赋值给一个变量 var file = $("#id_file")[0].files[0] // 3 把文件读到文件阅读器中 reader.readAsDataURL(file) // 4 等读完后,把文件阅读器的内容写到img标签上 //$("#id_img")[0].src=reader.result reader.onload = function () { //$("#id_img")[0].src=reader.result $('#id_img').attr('src', reader.result) } })
2.在views.py def register(request): if request.method == 'GET': register_form = RegisterForm() # context: 上下文 return render(request, 'register.html', context={'form': register_form}) else: # post请求的时候 res = {'code': 100, 'msg': '注册成功'} # 取出用户名密码,使用form校验数据,如果校验通过,存到数据库中,如果校验不通过,返回错误信息 register_form = RegisterForm(data=request.POST) if register_form.is_valid(): # 数据字段自己的规则,局部钩子,全局钩子都校验过后,通过了 # 1 re_password字段,不存到数据库的,剔除 register_data = register_form.cleaned_data register_data.pop('re_password') # 2 头像:如果携带了要存,头像是文件,在request.FILES中 my_file = request.FILES.get('my_file') if my_file: register_data['avatar'] = my_file # 2 存到数据库 UserInfo.objects.create_user(**register_data) # UserInfo.objects.create_user(username=register_data.get('username'),) 等同于上面,但是麻烦 return JsonResponse(res) else: res['code'] = 101 res['msg'] = '注册失败' res['errors'] = register_form.errors return JsonResponse(res)
注意: 项目后台静资源中得到图片,一般放在static文件夹下, 用户上传的文件,图片一般放在media文件夹下。文件路径先是在avatar文件夹下再是media文件夹下面, django中需要在配置文件中加一句话 MEDIA_ROOT = os.path.jojin(BASE_DIR, 'media')
//当点击注册按钮,发送ajax请求到后端的注册功能 $("#id_submit").click(function () { //上传文件,借助formdata对象 var formdata = new FormData() //方式一 {#formdata.append('username',$('#id_username').val())#} {#formdata.append('password',$('#id_password'.val()))#} {#formdata.append('re_password',$('#id_re_password'.val()))#} {#formdata.append('email',$('#id_email').val())#} {#formdata.append('my_file',$('#id_file')[0].files[0])#} //方式二:借助form表单批量处理 var data = $("#id_form").serializeArray() {#console.log(data)#} //使用for循环,把data中的数据,转存到formdata中 jquery的each循环 $.each(data, function (i, v) { //i为索引值, v是每个数据值 formdata.append(v.name, v.value) }) //文件单独再放进去,不能循环文件放进去,不然会出错的。 formdata.append('my_file', $('#id_file')[0].files[0]) //使用ajax向后端发送请求 //1. 三种编码格式:urlencoded, form-data,json //urlencoded 的默认格式:{name:xz, age;19}---》name=xz&age=19 $.ajax({ url: '/register/', type: 'post', processData: false, contentType: false, data: formdata, //view视图函数里面的JsonResponse的返回值 success: function (data) { console.log(data) if (data.code == 100) { //表示注册成功,跳转到登录页面 location.href = '/login/' } else { //前端显示错误信息 console.log(data) //两次密码不一致的错误渲染 {#if(data.errors['__all__']){#} {# $(".error").html(data.errors["__all__"])[0]#} {##} } //其他标签的错误渲染 $.each(data.errors, function (k,v){ console.log(k) console.log(v) if(k=="__all__"){ //两次密码不一致的错误信息 $(".error").html(v[0]) }else{ //链式调用,在对应的input后面的span中插入错误文字,把父div加入has-error类,整个框变红 $("#id_" + k).next().html(v[0]).parent().addClass('has-error') } }) //定时任务 setTimeout(function (){ //把所有span的文字去掉,把父类div中的has-error类去掉 $(".text-danger").html("").parent().removeClass('has-error') },3000) } })
# 前端通过get把用户传入,我们可以根据用户名查询数据库,如果用户名存在,返回存在。如果不存在,返回不存在 /check_username/?username=xzx def check_username(request): res = {'code':100, 'msg': '用户存在'} username = request.GET.get('username') user = UserInfo.objects.filter(username=username).first() if user: #用户存在 return JsonResponse(res) else: #用户不存在 res['code'] = 101 res['msg'] = '用户不存在' return JsonResponse(res)
$("#id_username").blur(function(){ $.ajax({ url:'/check_username/?username=' +$(this).val(), type: 'get', success:function (data){ if(data.code == 100){ //在span中插入错误信息 {# alter(data.msg) #} $("#id_username").next().html(data.msg) } } }) })