1 <div class="container-fluid">
2 <div class="row">
3 <div class="col-md-8 col-md-offset-2">
4 <h1 class="text-center">注册</h1>
5 <form id="myform"><!--这里不用form表单提交,只是单纯用一下form标签-->
6 {% csrf_token %}
7 {% for form in form_obj %}
8 <lable for="{{ form.auto_id }}">{{ form.label }}</lable>
9 {# form.auto_id 获取forms组件渲染的标签的id值(id_字段名)形式#}
10 {{ form }}
11 <span style="color: red"></span>
12 {% endfor %}
13 <div class="form-group">
14 <label for="myfile">上传头像
15 {% load static %}
16 <img src="{% static 'img/default.png' %}" id="myimg" alt="" width="80" style="margin-left:10px">
17 </label>
18 <input type="file" name="avatar" id="myfile" style="display:none">
19 </div>
20
21 <input type="button" class="btn btn-primary pull-right" value="注册" id="id_commit">
22 </form>
23
24 </div>
25 </div>
26 </div>
27 <script>
28
29 // 将上传的头像展示到前端页面。
30 $('#myfile').change(function () {
31 // 文件阅读器对象
32 // 1 先生成一个文件阅读器对象
33 let myFileReaderObj = new FileReader();
34 // 2 获取用户上传的头像文件
35 let fileObj = $(this)[0].files[0];
36 console.log(fileObj)
37 // 3 将文件对象交给阅读器对象读取
38 myFileReaderObj.readAsDataURL(fileObj) //阅读完之后其实就传到后端了。
39 console.log(myFileReaderObj)
40 // 4 利用文件阅读器 将文件展示到前端页面 修改src属性
41 //等待文件阅读器加载完毕后再执行
42 myFileReaderObj.onload = function () {
43 $('#myimg').attr('src', myFileReaderObj.result) //将图片文件读取出来放到src属性后面
44 }
45 })
46
47 // 发送ajax请求,发送的数据中既包含普通键值对,也包含文件
48 // 准备数据
49 $('#id_commit').click(function (){
50 // 1 借助于formData对象
51 let formDataObj = new FormData();
52 //2 添加普通键值对
53 $.each($('#myform').serializeArray(),function (index,obj){
54 // console.log($('#myform').serializeArray()) 输出形式 1:{name: 'username', value: 'jason'}
55 // 所以将他们一一添加进fromData对象中红
56 formDataObj.append(obj.name,obj.value)
57 })
58 // 2 添加文件数据 (也是key:value 的形式传入的)
59 formDataObj.append('avatar',$('#myfile')[0].files[0]);
60
61 // 发送请求
62 $.ajax({
63 url:'',
64 type:'post',
65 data:formDataObj,
66 //需要指定两个关键性参数
67 contentType:false, //不需要任何编码
68 processData: false, //不用对数据进行任何处理
69 success:function (args){
70 if (args.code == 1000){
71 //跳转到登录界面
72 window.onclick.href = args.url
73 }else {
74 //将对应的错误提示,展示到对应的input框下面
75 $.each(args.msg,function (index,obj){
76 //console.log(index,obj) // eg:username:array 所以 obj是一个数组
77 let targetId = '#id_'+index
78 //forms组件渲染的标签的id值都是(id_字段名)格式,所以要用拼接的方式得到id值
79 $(targetId).next().text(obj[0]).parent().addClass('has-error')
80 })
81 }
82 }
83 })
84 })
85
86 //给所有的input框绑定获取焦点事件
87 $('input').focus(function () {
88 $(this).next().text('').parent().removeClass('has-error')
89 })
90
91
92 </script>
1 from django.shortcuts import render, HttpResponse, redirect
2 from app01.myforms import MyRegForm
3 from app01 import models
4 from django.http import JsonResponse
5
6 # Create your views here.
7 def register(request):
8 form_obj = MyRegForm()
9 if request.method == 'POST':
10 back_dic = {'code': 1000, 'msg': ''}
11 # 校验数据是否合法
12 # # print(request.POST) # 得到QueryDict对象(一个字典)
13 form_obj = MyRegForm(request.POST) # 将字典里面的数据传给MyRegForm进行比对,有不对的会返回出来错误(error_messages)
14 # 判断数据是否合法
15 if form_obj.is_valid(): # 该方法只有在数据全部合法的情况下才会返回true
16 clean_data = form_obj.cleaned_data # 查看所有校验过的数据,并返回(字典格式)
17 clean_data.pop('confirm_password') # 删除确认密码的数据,为下面保存数据做铺垫
18 file_obj = request.FILES.get('avatar') # 用户头像一定要判断是否传值,不能直接添加到字典中
19 # # print(file_obj) # file_obj 是图片名字 222.jpg
20 if file_obj:
21 clean_data['avatar'] = file_obj
22 # 操作数据库保存数据
23 models.UserInfo.objects.create_user(**clean_data)
24 back_dic['url'] = '/login/' # 传一个地址过去 ,注册完成后跳转到登录界面
25 else:
26 back_dic['code'] = 2000
27 back_dic['msg'] = form_obj.errors # 查看所有不符合校验规则的参数以及不符合的原因
28 return JsonResponse(back_dic)
29 return render(request, 'register.html', locals())
1 from django import forms
2 from app01 import models
3
4
5 # 对forms表中输入框输入的内容的限制。
6
7
8 class MyRegForm(forms.Form):
9 username = forms.CharField(label='用户名', min_length=3, max_length=8,
10 error_messages={
11 'required': '用户名不能为空',
12 'min_length': '用户名最少三位',
13 'max_length': '用户名最大八位',
14 },
15 # 让标签有bootstrap样式
16 widget=forms.widgets.TextInput(attrs={'class': 'form-control'})
17 )
18 password = forms.CharField(label='密码', min_length=3, max_length=8,
19 error_messages={
20 'required': '密码不能为空',
21 'min_length': '密码最少三位',
22 'max_length': '密码最大八位',
23 },
24 # 让标签有bootstrap样式
25 widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'})
26 )
27 confirm_password = forms.CharField(label='确认密码', min_length=3, max_length=8,
28 error_messages={
29 'required': '确认密码不能为空',
30 'min_length': '确认密码最少三位',
31 'max_length': '确认密码最大八位',
32 },
33 # 让标签有bootstrap样式
34 widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'})
35 )
36 email = forms.EmailField(label='邮箱',
37 error_messages={
38 'required': '邮箱不能为空',
39 'invalid': '邮箱格式不正确',
40 },
41 widget=forms.widgets.EmailInput(attrs={'class': 'form-control'})
42 )
43
44 # 局部钩子 校验用户名是否已经存在
45 def clean_username(self):
46 username = self.cleaned_data.get('username')
47 # 去数据库中校验
48 is_exist = models.UserInfo.objects.filter(username=username)
49 if is_exist:
50 # 提示信息
51 self.add_error('username', '用户名已存在')
52 return username
53
54 # 全局钩子:校验两次密码是否一致
55 def clean(self):
56 password = self.cleaned_data.get('password')
57 confirm_password = self.cleaned_data.get('confirm_password')
58 if not password == confirm_password:
59 self.add_error('confirm_password', '两次密码不一致')
60 return self.cleaned_data