BBS注册功能
一、后端
1.组件校验数据
"""
@author RansySun
@create 2019-11-03-11:35
"""
from django import forms
from django.forms import widgets
from app import models
class MyRegForm(forms.Form):
"""创建注册标签"""
username = forms.CharField(min_length=3, max_length=9, label='用户名',
error_messages={
'min_length': '用户名不能少于六位',
'max_length': '用户名不能大于九位',
'required': '用户名不能为空'
}, widget=widgets.TextInput(attrs={'class': 'form-control'}))
password = forms.CharField(min_length=3, max_length=8, label='密 码',
error_messages={
'min_length': '密码不能少于六位',
'max_length': '密码不能多于八位',
'required': '密码不能为空'
}, widget=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=widgets.PasswordInput(attrs={'class': 'form-control'}))
email = forms.EmailField(label='邮箱',
error_messages={
'required': '邮箱不能为空',
'invalid': '邮箱格式不正确'
}, widget=widgets.EmailInput(attrs={'class': 'form-control'}))
def clean_username(self):
"""局部钩子,判断用户是否已经存在"""
username = self.cleaned_data.get('username')
user_obj = models.UserInfo.objects.filter(username=username)
if user_obj:
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
2.注册功能实现
# url.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^register/', views.register), # 注册
]
# views.register
def register(request):
"""
注册功能实现
:param request:
:return:
"""
# 组件校验数据
form_obj = MyRegForm()
if request.method == 'POST':
# 向前台返回结果信息
back_dic = {'code': 1000, "msg": ''}
form_obj = MyRegForm(request.POST)
# print(request.POST)
# print(request.FILES)
# 校验数据
if form_obj.is_valid(): # 验证所有表单是否全部通过
# form_obj.cleaned_data # {'username': 'randy', 'password': '123456', 'confirm_password': '123456', 'email': '2214644978@qq.com'}
cleaned_data = form_obj.cleaned_data # 所有验证通过的键值对
# 移除确认密码
cleaned_data.pop('confirm_password')
file_obj = request.FILES.get('avatar') # 获取用户头像, 如果没有上传, 则为空
if file_obj:
"""
获取用户上传头像之后,一定要判断用户是否上传了,
如果没有上传,字典中就不会加avatar键值对
"""
cleaned_data['avatar'] = file_obj
# 通过 ** 打散字典的方式作为参数, key必须与数据库中字段中一模一样
models.UserInfo.objects.create_user(**cleaned_data)
back_dic['url'] = '/login/'
else:
# 向前台返回发生错误信息
back_dic['code'] = 2000
back_dic['msg'] = form_obj.errors
print(back_dic)
return JsonResponse(back_dic)
return render(request, '01register.html', locals())
二、前端设计
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{% load static %}
<script src="{% static 'bootstrap/js/jquery.js' %}"></script>
<script src="{% static 'bootstrap/js/bootstrap.js' %}"></script>
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.css' %}">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 col-lg-offset-3">
<h1 class="text-center">注册界面</h1>
<form action="" class="form-horizontal" id="myform" novalidate>
{% csrf_token %}
{# 标签 #}
{% for f_obj in form_obj %}
<div class="form-group">
<label for="{{ f_obj.auto_id }}">{{ f_obj.label }} </label>
{{ f_obj }}
<span style="color:red" class="pull-right"></span>
</div>
{% endfor %}
{# 头像通过点击图片上传头像,隐藏file标签#}
<div class="form-group">
<label for="myfile">
头像<img src="{% static 'img/default1.png' %}" alt="" id="avatar" width="80px" height="80px"
style="margin: 10px 10px;border-radius: 50%">
</label>
<input type="file" id="myfile" name="avatar" style="display: none;">
</div>
{# 注册按钮,通过ajax检测登录信息, 报错提示#}
<input type="button" class="btn btn-success pull-right" id='commit' value="注册">
</form>
</div>
</div>
</div>
<script>
// 文件阅读器,
$('#myfile').change(function () {
// 将图片改为用户上传的图片
// 1.产生文件阅读器队形
var fileReader = new FileReader();
// 2.获取用户上传的文件
var fileUp = $(this)[0].files[0];
// 3.让文件阅读器读取该文件
fileReader.readAsDataURL(fileUp);
// 4.利用文件阅读器将文件展示出来
fileReader.onload = function () {
$('#avatar').attr('src', fileReader.result)
}
});
$('#commit').on('click', function () {
var formData = new FormData();
// serializeArray() 获取form表单中的键值对, each循环获取数组中内容
$.each($('#myform').serializeArray(), function (index, obj) {
formData.append(obj.name, obj.value)
});
// 添加上传的图片
formData.append('avatar', $('#myfile')[0].files[0]);
$.ajax({
url: '',
type: 'post',
data: formData,
contentType:false,
processData:false,
success: function (data) {
if (data.code == 1000) {
window.location.href = data.url
}else {
$.each(data.msg, function (index, obj) {
// data.msg是字段,所以index是key, obj value值是一个报错的数组信息
// 通过index手动拼接input框字段
var tagId = '#id_'+index;
{#alert(tagId)#}
// 获取出错的标签下面的span标签添加报错的信息,给父标签添加一个红色错误边框
$(tagId).next().text(obj[0]).parent().addClass('has-error')
});
}
}
});
$('input').focus(function () {
$(this).next().text('').parent().removeClass('has-error')
});
});
</script>
</body>
</html>