注册渲染:
<!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})
效果图:
