form.py
“”"
bbs用到的form类
“”"
from django import forms
from django.core.exceptions import ValidationError
from blog import models
# 定义一个注册的form类
class RegForm(forms.Form):
username = forms.CharField(
max_length=16,
label="用户名",
error_messages={
"max_length": "用户名最长16位",
"required": "用户名不能为空",
},
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": "邮箱不能为空",
}
)
# 重写username字段的局部钩子
def clean_username(self):
username = self.cleaned_data.get("username")
is_exist = models.UserInfo.objects.filter(username=username)
if is_exist:
# 表示用户名已注册
self.add_error("username", ValidationError("用户名已存在"))
else:
return username
# 重写email字段的局部钩子
def clean_email(self):
email = self.cleaned_data.get("email")
is_exist = models.UserInfo.objects.filter(email=email)
if is_exist:
# 表示邮箱已注册
self.add_error("email", ValidationError("邮箱已被注册"))
else:
return email
# 重写全局的钩子函数,对确认密码做校验
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
用户信息表models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
"""
用户信息表
"""
nid = models.AutoField(primary_key=True)
phone = models.CharField(max_length=11, null=True, unique=True)
avatar = models.FileField(upload_to="avatars/", default="avatars/default.png", verbose_name="头像")
create_time = models.DateTimeField(auto_now_add=True)
blog = models.OneToOneField(to="Blog", to_field="nid", null=True, on_delete=models.CASCADE)
def __str__(self):
return self.username
class Meta:
verbose_name = "用户"
verbose_name_plural = verbose_name
注册views.py
from django.shortcuts import render, redirect, HttpResponse
from django.http import JsonResponse
from django.contrib import auth
from geetest import GeetestLib
from blog import forms, models
# 注册的视图函数
def register(request):
if request.method == "POST":
ret = {"status": 0, "msg": ""}
form_obj = forms.RegForm(request.POST)
print(request.POST)
# 帮我做校验
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对象
form_obj = forms.RegForm()
print(form_obj.fields)
return render(request, "register.html", {"form_obj": form_obj})
HTML文件
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<form novalidate autocomplete="off" 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>
<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标签中
console.log(fileReader.result)
$("#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, // 告诉jQuery不要处理我的数据
contentType: false, // 告诉jQuery不要设置content类型
data: formData,
success:function (data) {
if (data.status){
// 有错误就展示错误
// console.log(data.msg);
// 将报错信息填写到页面上
$.each(data.msg, function (k,v) {
//遍历每个错误
// console.log("id_"+k, v[0]);
//将错误添加到span标签,给爷爷标签加上has-error
$("#id_"+k).next("span").text(v[0]).parent().parent().addClass("has-error");
})
}else {
// 没有错误就跳转到指定页面/index/
location.href = data.msg;
}
}
})
});
// 将所有的input框绑定获取焦点的事件,将所有的错误信息清空
$("form input").focus(function () {
$(this).next().text("").parent().parent().removeClass("has-error");
});
// 给username input框绑定一个失去焦点的事件,失去焦点之后就校验用户名是否已被注册
$("#id_username").on("input", function () {
// 取到用户填写的值
var username = $(this).val();
// 发请求
$.ajax({
url: "/check_username_exist/",
type: "get",
data: {"username": username},
success: function (data) {
if (data.status){
// 用户名已被注册
$("#id_username").next().text(data.msg).parent().parent().addClass("has-error");
}
}
})
})
</script>