下面的代码是老男孩课程基于Form组件和AJAX以及Django的auth组件的注册程序。
register.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>欢迎注册</title>
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="/static/mystyle.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<form novalidate action="/reg/" method="post" class="form-horizontal reg-form" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group">
<label for="{{ form_obj.username.id_for_label }}"
class="col-sm-2 control-label">{{ form_obj.username.label }}</label>
<div class="col-sm-8">
{{ form_obj.username }}
<span class="help-block">{{ form_obj.username.errors.0 }}</span>
</div>
</div>
<div class="form-group">
<label for="{{ form_obj.password.id_for_label }}"
class="col-sm-2 control-label">{{ form_obj.password.label }}</label>
<div class="col-sm-8">
{{ form_obj.password }}
<span class="help-block">{{ form_obj.password.errors.0 }}</span>
</div>
</div>
<div class="form-group">
<label for="{{ form_obj.re_password.id_for_label }}"
class="col-sm-2 control-label">{{ form_obj.re_password.label }}</label>
<div class="col-sm-8">
{{ form_obj.re_password }}
<span class="help-block">{{ form_obj.re_password.errors.0 }}</span>
</div>
</div>
<div class="form-group">
<label for="{{ form_obj.email.id_for_label }}"
class="col-sm-2 control-label">{{ form_obj.email.label }}</label>
<div class="col-sm-8">
{{ form_obj.email }}
<span class="help-block">{{ form_obj.email.errors.0 }}</span>
</div>
</div>
<div class="form-group">
<label
class="col-sm-2 control-label">头像</label>
<div class="col-sm-8">
<label for="id_avatar"><img id="avatar-img" src="/static/img/default.png" alt=""></label>
<input accept="image/*" type="file" name="avatar" id="id_avatar" style="display: none">
<span class="help-block"></span>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="button" class="btn btn-success" id="reg-submit">注册</button>
</div>
</div>
</form>
</div>
</div>
</div>
<script src="/static/jquery-3.3.1.js"></script>
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
<script>
// 找到头像的input标签绑定change事件
$("#id_avatar").change(function () {
// 1. 创建一个读取文件的对象
var fileReader = new FileReader();
// 取到当前选中的头像文件
// console.log(this.files[0]);
// 读取你选中的那个文件
fileReader.readAsDataURL(this.files[0]); // 读取文件是需要时间的
fileReader.onload = function () {
// 2. 等上一步读完文件之后才 把图片加载到img标签中
$("#avatar-img").attr("src", fileReader.result);
};
});
// AJAX提交注册的数据
$("#reg-submit").click(function () {
// 取到用户填写的注册数据,向后端发送AJAX请求
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("avatar", $("#id_avatar")[0].files[0]);
formData.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val());
$.ajax({
url: "/reg/",
type: "post",
processData: false,
contentType: false,
data : formData,
success:function (data) {
if (data.status){
// 有错误就展示错误
// console.log(data.msg);
// 将报错信息填写到页面上
$.each(data.msg, function (k,v) {
// console.log("id_"+k, v[0]);
// console.log($("#id_"+k));
$("#id_"+k).next("span").text(v[0]).parent().parent().addClass("has-error");
})
}else {
// 没有错误就跳转到指定页面
location.href = data.msg;
}
}
})
});
// 将所有的input框绑定获取焦点的事件,将所有的错误信息清空
$("form input").focus(function () {
$(this).next().text("").parent().parent().removeClass("has-error");
})
</script>
</body>
</html>
forms.py
"""
bbs用到的form类
"""
from django import forms
from django.core.exceptions import ValidationError
# 定义一个注册的form类
class RegForm(forms.Form):
username = forms.CharField(
max_length=16,
label="用户名",
error_messages={
"max_length": "用户名最长16位",
"required": "用户名不能为空",
},
#通过表单的widgets属性可以设置生辰的HTML代码的CSS样式,widgets还有其他的用途。
widget=forms.widgets.TextInput(
attrs={"class": "form-control"},
)
)
password = forms.CharField(
min_length=6,
label="密码",
widget=forms.widgets.PasswordInput(
attrs={"class": "form-control"},
render_value=True,
),
error_messages={
"min_length": "密码至少要6位!",
"required": "密码不能为空",
}
)
re_password = forms.CharField(
min_length=6,
label="确认密码",
widget=forms.widgets.PasswordInput(
attrs={"class": "form-control"},
render_value=True,
),
error_messages={
"min_length": "确认密码至少要6位!",
"required": "确认密码不能为空",
}
)
email = forms.EmailField(
label="邮箱",
widget=forms.widgets.EmailInput(
attrs={"class": "form-control"},
),
error_messages={
"invalid": "邮箱格式不正确!",
"required": "邮箱不能为空",
}
)
# 重写全局的钩子函数,对确认密码做校验
def clean(self):
password = self.cleaned_data.get("password")
re_password = self.cleaned_data.get("re_password")
if re_password and re_password != password:
self.add_error("re_password", ValidationError("两次密码不一致"))
else:
return self.cleaned_data
views.py
def register(request):
#如果表单提交用的是 POST 请求,那么该视图将创建一个表单实例并使用请求中的数据填充它: form = NameForm(request.POST) 这叫“绑定数据到表单”
if request.method == "POST":
ret = {"status": 0, "msg": ""}
form_obj = forms.RegForm(request.POST)
print(request.POST)
# 帮我做校验
# Form表单的实例含有is_valid()方法,这个方法会对传进forms对象的数据进行校验,如果所有数据都符合要求,那么该方法会返回True,然后把表单数据放到cleaned_data中,cleaned_data会字典形式的数据。
if form_obj.is_valid():
# 校验通过,去数据库创建一个新的用户
form_obj.cleaned_data.pop("re_password")
avatar_img = request.FILES.get("avatar")
models.UserInfo.objects.create_user(**form_obj.cleaned_data, avatar=avatar_img)
ret["msg"] = "/index/"
return JsonResponse(ret)
else:
print(form_obj.errors)
ret["status"] = 1
ret["msg"] = form_obj.errors
print(ret)
print("=" * 120)
return JsonResponse(ret)
# 生成一个form对象
#如果是get方式请求,则直接返回form表单
form_obj = forms.RegForm()
print(form_obj.fields)
return render(request, "register.html", {"form_obj": form_obj})