目录
BBS项目之注册功能思路总结
一、项目注册功能概览
- 渲染前端标签
- 校验用户数据
- 展示错误提示
二、项目注册功能步骤详细
1. 开设路由跳转
# 注册功能
path('register/', views.register_func, name='register_view'),
2.写视图函数
from django.shortcuts import render, HttpResponse, redirect
def register_func(request):
return render(request, 'registerPage.html', locals())
3.创建前端html注册页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<div class="container">
<div class="col-md-8 col-md-offset-2">
<h2 class="text-center">用户注册</h2>
</div>
</div>
4.写forms校验类
from django import forms
from app01 import models
class RegisterForm(forms.Form):
"""用户注册form类"""
username = forms.CharField(min_length=3, max_length=8, label='用户名',
error_messages={
'min_length': '用户名最短三位',
'max_length': '用户名最长八位',
'required': '用户名不能为空'
},
widget=forms.widgets.TextInput(attrs={'class': 'form-control'})
)
password = forms.CharField(min_length=3, max_length=8, label='密码',
error_messages={
'min_length': '密码最短三位',
'max_length': '密码最长八位',
'required': '密码不能为空'
},
widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'})
)
confirm_password = forms.CharField(min_length=3, max_length=8, label='确认密码',
error_messages={
'min_length': '密码最短三位',
'max_length': '密码最长八位',
'required': '密码不能为空'
},
widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'})
)
email = forms.EmailField(label='邮箱',
error_messages={
'required': '密码不能为空',
'invalid': '邮箱格式不正确'
},
widget=forms.widgets.EmailInput(attrs={'class': 'form-control'})
)
# 局部钩子校验用户名是否已存在
def clean_username(self):
username = self.cleaned_data.get('username')
res = models.UserInfo.objects.filter(username=username)
if res:
self.add_error('username', '用户名已存在')
return username
# 全局钩子校验两次密码是否一致
def clean(self):
password = self.cleaned_data.get('password')
confirm_password = self.cleaned_data.get('confirm_password')
if not password == confirm_password:
self.add_error('confirm_password', '两次密码不一致')
return self.cleaned_data
5.在views.py里注册视图函数产生forms类对象
# 1.先产生一个空的form_obj
form_obj = myforms.RegisterForm()
6.前端渲染注册样式
<form id="form"> <!--不使用form表单提交数据 但是用一下form标签 它有一个序列化功能-->
{% csrf_token %}
{% for form in form_obj %}
<div class="form-group"> <!--目的是让多个获取用户数据的标签上下间距更大一些-->
<label for="{{ form.auto_id }}">{{ form.label }}</label> <!--form.auto_id自动获取渲染的标签id值-->
{{ form }}
<span style="color: red" class="pull-right"></span>
</div>
{% endfor %}
<!--用户头像自己编写相关标签获取-->
<div class="form-group">
<label for="myfile">头像
<img src="/static/img/default.jpg" alt="" width="120" id="myimg">
</label>
<input type="file" id="myfile" style="display: none">
</div>
<input type="button" id="subBtn" class="btn btn-primary btn-block" value="注册">
</form>
7.头像实时展示 绑定点击事件 发送Ajax请求
<script>
// 1.用户头像的实时展示
$('#myfile').change(function () {
// 1.产生一个文件阅读器对象
let myFileReaderObj = new FileReader();
// 2.获取用户上传的头像文件
let fileObj = this.files[0];
// 3.将文件对象交给阅读器对象读取
myFileReaderObj.readAsDataURL(fileObj);
// 等待文件阅读器对象加载完毕之后再修改src
myFileReaderObj.onload = function () {
// 4.修改img标签的src属性展示图片
$('#myimg').attr('src', myFileReaderObj.result)
}
})
// 2.给注册按钮绑定点击事件 发送ajax 携带了文件数据
$('#subBtn').click(function () {
// 1.先产生一个内置对象
let myFormDataObj = new FormData();
// 2.添加普通数据(单个单个的编写效率极低)
$.each($('#form').serializeArray(), function (index, dataObj) { // 对结果for循环 然后交给后面的函数处理
myFormDataObj.append(dataObj.name, dataObj.value) // {'name':'','value':''}
})
// 3.添加文件数据
myFormDataObj.append('avatar', $('#myfile')[0].files[0])
// 4.发送ajax请求
$.ajax({
url:'',
type:'post',
data:myFormDataObj,
contentType:false,
processData: false,
success:function (args) {
if(args.code === 10000){
window.location.href = args.url
}else{
let dataObj = args.msg;
// 如何针对性的渲染错误提示 {'username'} id_username
$.each(dataObj, function (k, msgArray) {
// 拼接标签的id值
let eleId = '#id_' + k
// 根据id查找标签 修改下面span标签的内容 并给父标签添加错误样式
$(eleId).next().text(msgArray[0]).parent().addClass('has-error')
})
}
}
})
})
// 3.给所有的input标签绑定获取焦点事件 移除错误样式
$('input').focus(function () {
$(this).next().text('').parent().removeClass('has-error')
})
</script>
8.后端注册功能正确的业务逻辑
if request.method == "POST":
form_obj = myforms.RegisterForm(request.POST) # username password confirm_password email csrfmiddlewaretoken
if form_obj.is_valid():
clean_data = form_obj.cleaned_data # 存储符合校验的数据 {username password confirm_password email}
# 将confirm_password键值对移除
clean_data.pop('confirm_password') # {username password email}
# 获取用户上传的头像文件
avatar_obj = request.FILES.get('avatar') # 用户有可能没有上传
if avatar_obj:
clean_data['avatar'] = avatar_obj # {username password email avatar }
# 创建用户数据
models.UserInfo.objects.create_user(**clean_data) # 上述处理字典的目的就是为了创建数据省事
back_dict['msg'] = '注册成功'
back_dict['url'] = '/login/'
9.后端注册功能错误的业务逻辑
# 前后端ajax交互 通常采用字段作为交互对象
back_dict = {'code': 10000, 'msg': ''}
else:
back_dict['code'] = 10001
back_dict['msg'] = form_obj.errors
return JsonResponse(back_dict)