今日学习内容
一、注册forms编写
创建一个文件关于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)
}
}
})
})
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/python/289708.html