带上传头像注册功能的实现
注册
注册是每个网站必不可少的一部分,通过注册来增加网站用户。
实现注册功能在 Django 中非常方便,利用 Django 自带的 Form 模块可以快速生成注册用的 Form 表单,利用 Django 自带的 Auth 模块可以自定义用户表的字段。
本文要实现的是通过 AJAX 异步发送数据,带上传头像图片的注册方式。
此时,在 models 数据表、HTML 页面、视图函数都会有一定变化。
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")
create_time = models.DateTimeField(auto_now_add=True)
blog = models.OneToOneField(to="Blog", to_field="nid", null=True)
def __str__(self):
return self.username
首先,为了方便使用 Django 自带的认证系统,用户信息表继承了抽象用户类,此时需要在 setting 中设置次表为默认的认证表。
# 告诉Django项目用哪张表做认证
AUTH_USER_MODEL = 'blog.UserInfo'
其次,重要的是 avatar 字段,是 FileFiled 字段,需要设置文件上传的文件夹和默认的文件。
avatar = models.FileField(upload_to="avatars/", default="avatars/default.png")
HTML 页面
首先是上传图片文件的 input 元素的隐藏和预览,可以参考:注册时头像预览功能的实现
在 form 表单中有上传文件的 input 标签时,需要在 form 标签中设置属性 enctype="multipart/form-data"
重要的点是 AJAX 提交带文件的数据。
// AJAX提交注册的数据
$("#reg-submit").click(function () {
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, // 告诉Jqu不要设置content类型
data: formData,
success: function (data) {
if (data.status) {
// 将错误信息填写到页面上
$.each(data.msg, function (k, v) {
$("#id_" + k).next("span").text(v[0]).parent().parent().addClass("has-error");
})
} else {
// 没有错误就跳转到指定页面
location.href = data.msg
}
}
});
});
注意:
-
因为有文件数据,所以在通过 AJAX 往后端传数据时使用 FormData 对象。
formData.append("avatar", $("#id_avatar")[0].files[0]);
-
因为有文件数据,所以在通过 AJAX 往后端传数据时需要设置以下属性:
processData: false, // 告诉JQuery不要处理我的数据 contentType: false, // 告诉Jqu不要设置content类型
视图函数
def register(request):
if request.method == "POST":
ret = {"status": 0, "msg": ""}
form_obj = forms.RegForm(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:
ret["status"] = 1
ret["msg"] = form_obj.errors
return JsonResponse(ret)
form_obj = forms.RegForm()
return render(request, "register.html", {"form_obj": form_obj})
在后端获得上传文件路径的方法:
avatar_img = request.FILES.get("avatar")
在成功上传头像文件后,数据库中头像字段保存的是在后端文件的路径。
avatar_database
GitHub 地址:https://github.com/protea-ban/oldboy/tree/master/s9day76/bbs