form组件注册ajax登录auth认证及验证码

本项目采用django自带的数据库

项目文件

  

 

models.py

1 from django.db import models
2 from django.contrib.auth.models import AbstractUser
3 # Create your models here.
4  
5 class Userinfo(AbstractUser):
6     email = models.EmailField()
View Code

settings.py

1 AUTH_USER_MODEL='app01.Userinfo'#自定义认证表
2 LOGIN_URL='/login/'#指定认证失败的跳转页面
3  
4 STATIC_URL = '/static/'
5 STATICFILES_DIRS=[
6     os.path.join(BASE_DIR,'static_files')
7 ]
settings.py

views.py

  1 from django.shortcuts import render, HttpResponse, redirect
  2 from django import forms#django的form组件
  3 from django.core.validators import RegexValidator#form组件中的validators自带校验器
  4 from django.core.exceptions import ValidationError#错误
  5 import re
  6 from app01 import models
  7 from django.http import JsonResponse#Json响应数据类型
  8 from django.urls import reverse#url反向解析
  9 from django.contrib import auth#django内置认证系统
 10 from django.contrib.auth.decorators import login_required#认证装饰器
 11  
 12  
 13 # Create your views here.
 14 #自定义校验函数
 15 def name_valid(value):
 16     name_re = re.compile(r'^[\d]+')
 17     ret = name_re.match(value)
 18     if ret:
 19         raise ValidationError('用户名不能以数字开头!')
 20  
 21 #注册form组件
 22 class RegisterForm(forms.Form):
 23     name = forms.CharField(
 24         required=True,
 25         label='用户名:',
 26         min_length=6,
 27         max_length=32,
 28         help_text='只能有字母数字下划线组成,且不能以数字开头,长度6到32位!',
 29         # initial='admin123_',
 30         error_messages={
 31             'required': '用户名不能为空!',
 32             'min_length': '长度不能少于6位!',
 33             'max_length': '长度不能超过32位!',
 34         },
 35         validators=[RegexValidator(r'^[a-zA-Z0-9_]+$', '用户名只能包含字母数字下划线!'), name_valid],
 36     )
 37     password = forms.CharField(
 38         required=True,
 39         label='密码:',
 40         min_length=6,
 41         max_length=32,
 42         help_text='长度6到32位!',
 43         initial='',
 44         error_messages={
 45             'required': '密码不能为空!',
 46             'min_length': '长度不能少于6位!',
 47             'max_length': '长度不能超过32位!',
 48         },
 49         widget=forms.PasswordInput(render_value=True),
 50     )
 51     r_password = forms.CharField(
 52         required=True,
 53         label='确认密码:',
 54         min_length=6,
 55         max_length=32,
 56         help_text='长度6到32位!',
 57         initial='',
 58         error_messages={
 59             'required': '密码不能为空!',
 60             'min_length': '长度不能少于6位!',
 61             'max_length': '长度不能超过32位!',
 62         },
 63         widget=forms.PasswordInput(render_value=True),
 64     )
 65     email = forms.EmailField(
 66         required=True,
 67         label='邮箱',
 68         error_messages={
 69             'required': '邮箱不能为空!',
 70             'invalid':'邮箱格式不正确!'
 71         }
 72     )
 73     #全部字段添加样式
 74     def __init__(self, *args, **kwargs):
 75         super(RegisterForm, self).__init__(*args, **kwargs)
 76         for field in self.fields:
 77             self.fields[field].widget.attrs.update({'class': 'form-control'})
 78     #局部钩子
 79     def clean_name(self):
 80         pass
 81         return self.cleaned_data.get('name')
 82  
 83     def clean_password(self):
 84         pass
 85         return self.cleaned_data.get('password')
 86  
 87     def clean_r_password(self):
 88         pass
 89         return self.cleaned_data.get('r_password')
 90  
 91     def clean_email(self):
 92         pass
 93         return self.cleaned_data.get('email')
 94     #全局钩子
 95     def clean(self):
 96         password = self.cleaned_data.get('password')
 97         r_password = self.cleaned_data.get('r_password')
 98         if password != r_password:
 99             self.add_error('r_password', '两次密码不一致!')
100             raise ValidationError('两次密码不一致!')
101         else:
102             return self.cleaned_data
103  
104  
105 # 注册
106 def register(request):
107     if request.method == 'GET':
108         register_obj = RegisterForm()
109         return render(request, 'register.html', {'register_obj': register_obj})
110     elif request.method == 'POST':
111         data = request.POST
112         # print(data)
113         register_obj = RegisterForm(data)
114         if register_obj.is_valid():
115             user_obj = register_obj.cleaned_data
116             print(user_obj)
117             username = user_obj.get('name')
118             password = user_obj.get('password')
119             email = user_obj.get('email')
120  
121             if not models.Userinfo.objects.filter(username=username).exists():
122                 new_obj = models.Userinfo.objects.create_user(username=username, password=password, email=email)
123                 print(f'新用户{username}注册成功!')
124                 return redirect('login')
125             else:
126                 register_obj.add_error('name', '用户名已存在!')
127                 return render(request, 'register.html', {'register_obj': register_obj})
128  
129         else:
130             return render(request, 'register.html', {'register_obj': register_obj})
131  
132 #登录页面的ModelForm组件(本次未使用)
133 '''
134 # class LoginForm(forms.ModelForm):
135 #     class Meta:
136 #         model = models.Userinfo  # 指定类
137 #         # fields='__all__'
138 #         # exclude=[]        #排除字段
139 #         fields = ['username', 'password']  # 设置的字段
140 #         labels = {  # 标签名
141 #             'username': '用户名:',
142 #             'password': '密码:'}
143 #         error_messages = {  # 错误信息
144 #             'username': {'required': '用户名不能为空!'},
145 #             'password': {'required': '密码不能为空!'},
146 #         }
147 #         widgets = {  # 插件
148 #             'username': forms.TextInput({"class": "form-control"}),
149 #             'password': forms.TextInput({"class": "form-control"}),
150 #
151 #         }
152 #         # def clean_username(self):
153 #         #     pass
154 #         #     return self.cleaned_data.get('username')
155 #         # def clean(self):
156 #         #     pass
157 #         #     return self.cleaned_data
158 #         # def __init__(self,*args,**kwargs):
159 #         #     super().__init__(*args,**kwargs)
160 #         #     for field in self.fields:
161 #         #         self.fields[field].widget.attrs.update({'class':'form-control'})
162  
163 '''
164  
165  
166  
167  
168  
169 #随机验证码
170 def get_cverification_code(request):
171     import os
172     from crmtest import settings
173     import random
174     def get_random_color():
175         '''
176         随机颜色
177         :return: rgb颜色
178         '''
179         return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
180  
181     from PIL import Image, ImageDraw, ImageFont#要先安装pillow模块:pip install pillow
182     img_obj = Image.new('RGB', (120, 40), get_random_color())#实例化图片对象
183     draw_obj = ImageDraw.Draw(img_obj)#创建图片
184  
185     font_path = os.path.join(settings.BASE_DIR, r'static_files\fonts\BRUX.otf')#字体路径(字体自己下载)
186     print('>>>>', font_path)
187     # font_obj = ImageFont.truetype(font_path, 26)#路径拼接注意不能有中文,否则报错
188     font_obj = ImageFont.truetype(r'static_files/fonts/BRUX.otf', 26) #相对路径r'static_files/fonts/BRUX.otf'
189     # font_obj = ImageFont.load_default().font#系统默认字体
190     sum_str = ''
191     for i in range(6):#生成随机的字母数字组合
192         a = random.choice([str(random.randint(0, 9)), chr(random.randint(97, 122)),
193                            chr(random.randint(65, 90))])  # 4  a  5  D  6  S
194         sum_str += a
195     print(sum_str)
196     draw_obj.text((12, 2), sum_str, fill=get_random_color(), font=font_obj)
197  
198     width = 120
199     height = 40
200     # 添加噪线
201     for i in range(5):#循环一次就是一条线:两点确定一条
202         x1 = random.randint(0, width)
203         x2 = random.randint(0, width)
204         y1 = random.randint(0, height)
205         y2 = random.randint(0, height)
206         draw_obj.line((x1, y1, x2, y2), fill=get_random_color())
207     # # 添加噪点
208     for i in range(10):
209         # 这是添加点,50个点
210         draw_obj.point([random.randint(0, width), random.randint(0, height)], fill=get_random_color())
211         # 下面是添加很小的弧线,看上去类似于一个点,50个小弧线
212         x = random.randint(0, width)
213         y = random.randint(0, height)
214         draw_obj.arc((x, y, x + 4, y + 4), 0, 90, fill=get_random_color())
215  
216     from io import BytesIO#生成的图片格式指定和存在位置(缓存)
217     f = BytesIO()
218     img_obj.save(f, 'png')
219     data = f.getvalue()
220  
221     # 验证码对应的数据保存到session里面
222     request.session['valid_str'] = sum_str
223  
224     return HttpResponse(data)
225  
226 # 登录
227 def login(request):
228     if request.method == 'GET':
229         return render(request, 'login.html')
230     elif request.method == 'POST':
231         # print(request.POST)
232         username = request.POST.get('username')
233         password = request.POST.get('password')
234         cverification_code=request.POST.get('cverification_code')
235  
236         if cverification_code.upper()==request.session.get('valid_str').upper():
237  
238             user_obj = auth.authenticate(username=username, password=password)
239             print(user_obj)
240             if user_obj:
241                 auth.login(request, user_obj)
242                 return JsonResponse({'status': 1, 'url': reverse('index')})
243             else:
244                 return JsonResponse({'status': 0, 'url': '账号或密码有误!'})
245         else:
246             return JsonResponse({'status': 0, 'url': '验证码输入有误!'})
247  
248  
249 #状态认证的首页访问(使用装饰器认证状态失败,会自动跳转一个路径,可以在settings中配置指定LOGIN_URL='/login/')
250 #同时在页面的请求路径会自动加上'?next=/index/'(当前页面路径),
251 # 借此可以在前端通过location.search获取后slice切边获取路径,登录成功之后在success回调函数location.href指向该路径,自动跳转访问的页面
252 @login_required
253 def index(request):
254     # if request.user.is_authenticated:
255     print(request.user)
256     if request.method == 'GET':
257         return render(request, 'index.html')
258 # else:
259 #     return redirect('login')
260  
261  
262 #不加装饰器的方法判断状态
263 '''
264 def index(request):
265     if request.user.is_authenticated:
266         print(request.user)
267         if request.method == 'GET':
268             return render(request, 'index.html')
269     else:
270         return redirect('login')
271 '''
272  
273  
274 #注销
275 def logout(request):
276     auth.logout(request)
277     return redirect('login')
278  
279 #修改密码
280 def reset_psd(request):
281     if request.user.is_authenticated:
282         if request.method == 'GET':
283             return render(request, 'reset_psd.html')
284         elif request.method == 'POST':
285             old_password = request.POST.get('old_password')
286             new_password = request.POST.get('new_password')
287             r_new_password = request.POST.get('r_new_password')
288             # ret=request.user.check_password(old_password)
289             # print(ret)
290             if request.user.check_password(old_password):
291                 if new_password == r_new_password:
292                     request.user.set_password(new_password)
293                     request.user.save()
294                     return JsonResponse({'status': True, 'info': '操作成功!', 'url': reverse('index')})
295                 else:
296                     return JsonResponse({'status': False, 'info': '两次新密码不一致!', 'url': ''})
297             else:
298                 return JsonResponse({'status': False, 'info': '操作失败:原密码输入有误!', 'url': ''})
299         return JsonResponse({'status': False, 'info': '操作失败!', 'url': ''})
300  
301     else:
302         return redirect('login')
views.py

 urls.py

 1 from django.conf.urls import url
 2 from django.contrib import admin
 3 from app01 import views
 4  
 5 urlpatterns = [
 6     url(r'^admin/', admin.site.urls),
 7     url(r'^register/', views.register, name='register'),
 8     url(r'^login/', views.login, name='login'),
 9     url(r'^index/', views.index, name='index'),
10     url(r'^logout/', views.logout, name='logout'),
11     url(r'^reset_psd/', views.reset_psd, name='reset_psd'),
12     url(r'^get_cverification_code/', views.get_cverification_code, name='get_cverification_code'),#随机验证码
13  
14 ]
urls.py

templates

register.html

 1 {% load static %}
 2 <!DOCTYPE html>
 3 <html lang="en">
 4 <head>
 5     <meta charset="UTF-8">
 6     <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
 7  
 8     <title>用户注册</title>
 9 </head>
10 <body style="background-image: url('{% static 'images/register_bg.gif' %}');background-size: cover">
11 <div class="container">
12     <div class="row">
13         <div class="col-xs-6 col-xs-offset-3" style="margin-top: 12%;">
14             <div class="container-fluid" style="background-color: rgba(255,255,255,0.2);border-radius: 5%">
15                 <div class="row">
16                     <h2 class="text-left col-xs-8 text-primary">新用户注册:</h2>
17                 </div>
18                 <div class="row" >
19                     <form action="{% url 'register' %}" method="post" novalidate class="form-horizontal">
20                         {% csrf_token %}
21                         {% for field in register_obj %}
22                             <div class="form-group" >
23                                 <label for="{{ field.id_for_label }}"
24                                        class="col-xs-3 control-label" >{{ field.label }}</label>
25                                 <div class="col-xs-7">
26                                     {{ field }}
27                                     <div style="height: 10px;" class="text-danger">{{ field.errors.0 }}</div>
28                                 </div>
29                             </div>
30                         {% endfor %}
31                         <div class="form-group">
32                             <div class="col-sm-7  col-xs-offset-3">
33                                 <span class="col-xs-10 text-success text-center"
34                                       style="line-height: 200%">已有账号,请<a href="{% url 'login' %}">登录</a></span>
35                                 <input type="submit" class="btn btn-success btn-sm col-xs-2 pull-right">
36  
37                             </div>
38                         </div>
39                     </form>
40                 </div>
41             </div>
42         </div>
43     </div>
44 </div>
45  
46 </body>
47 <script src="{% static 'jquery-3.4.1.js' %}"></script>
48 <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>
49 </html>
register.html

  login.html

  1 {% load static %}
  2 <!DOCTYPE html>
  3 <html lang="en">
  4 <head>
  5     <meta charset="UTF-8">
  6     <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
  7     <title>用户登录</title>
  8 </head>
  9 <body style="background-image: url('{% static "images/login_bg.jpg" %}');background-size: cover">
 10 <div>
 11     <div class="container">
 12         <div class="row">
 13             <div class='col-xs-4 col-xs-offset-4'>
 14                 <div class="row" style="margin-top: 50%;background-color: rgba(255,255,255,0.2 );border-radius: 3%">
 15                     <div class="row c1">
 16                         <h2 class=" col-xs-6  text-primary" style="margin-bottom: 30px">用户登录</h2>
 17                     </div>
 18                     <div class="row">
 19                         <div class="form-group" style="height: 60px;">
 20                             <label for="username" class="col-xs-3 control-label text-right">用户名:</label>
 21                             <div class="col-xs-8">
 22                                 <input type="text" class="form-control" id="username">
 23                                 <div class="text-danger"></div>
 24                             </div>
 25                         </div>
 26                         <div class="form-group" style="height: 60px;">
 27                             <label for="password" class="col-xs-3 control-label text-right">密码:</label>
 28                             <div class="col-xs-8">
 29                                 <input type="password" class="form-control" id="password">
 30                                 <div class="text-danger"></div>
 31                             </div>
 32                         </div>
 33  
 34                         <div class="form-group" style="height: 60px;">
 35                             <label for="code" class="col-xs-3 control-label text-right">验证码:</label>
 36                             <div class="col-xs-4">
 37                                 <input type="text" class="form-control" id="code">
 38                                 <div class="text-danger"></div>
 39                             </div>
 40                             <div class="col-xs-5" style="padding-left: 0"><img src="{% url 'get_cverification_code' %}"
 41                                                                                alt="" id="cverification_code"></div>
 42                         </div>
 43  
 44                         <div class="form-group" style="height: 60px;">
 45                             {% csrf_token %}
 46                             <div class="col-xs-8 col-xs-offset-3">
 47                                 <a href="{% url 'register' %}">
 48                                     <button class="btn btn-primary col-xs-offset-2" id="register">注册</button>
 49                                 </a>
 50                                 <button class="btn btn-success col-xs-offset-2" id="submit">登录</button>
 51                                 <div class=" text-danger"></div>
 52                             </div>
 53                         </div>
 54                     </div>
 55                 </div>
 56             </div>
 57         </div>
 58     </div>
 59 </div>
 60  
 61 </div>
 62 </div>
 63 </body>
 64 <script src="{% static 'jquery-3.4.1.js' %}"></script>
 65 <script src="{% static 'jquery-cookie-1.4.1.js' %}"></script>
 66 <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>
 67 <script>
 68     $(function () {
 69         
 70         $('#cverification_code').on('click',function () {
 71             var src='{% url "get_cverification_code" %}?temp='+Math.random();
 72             console.log(src);
 73             $('#cverification_code').attr('src',src);
 74         });
 75         
 76         
 77         
 78         $('#username').blur(function () {
 79             if (username !== '') {
 80                 $('#username').next().text('');
 81             }
 82         });
 83         $('#password').blur(function () {
 84             if (username !== '') {
 85                 $('#password').next().text('');
 86             }
 87         });
 88         $('#code').blur(function () {
 89             if (username !== '') {
 90                 $('#code').next().text('');
 91             }
 92         });
 93         $('#username').focus(function () {
 94             if (username !== '') {
 95                 $('#submit').next().text('');
 96             }
 97         });
 98         $('#password').focus(function () {
 99             if (username !== '') {
100                 $('#submit').next().text('');
101             }
102         });
103         $('#code').focus(function () {
104             if (username !== '') {
105                 $('#code').next().text('');
106             }
107         });
108  
109  
110         $('#submit').click(function () {
111  
112             var username = $('#username').val().trim();
113             var password = $('#password').val().trim();
114             var cverification_code = $('#code').val().trim();
115             console.log(cverification_code);
116             console.log(cverification_code.length);
117  
118  
119             if (username === '' || password === '' || cverification_code.length !== 6) {
120                 if (username === '') {
121                     $('#username').next().text('用户名不能为空!');
122                 }
123                 ;
124                 if (password === '') {
125                     $('#password').next().text('密码不能为空!')
126                 }
127                 ;
128                 if (cverification_code.length !== 6) {
129                     $('#code').next().text('验证码为6位!');
130                 }
131                 ;
132                 console.log(cverification_code.length);
133                 if (cverification_code.length !== 6) {
134                     $('#code').next().text('验证码为6位!');
135                     return false
136                 }
137                 ;
138  
139             } else {
140                 $.ajax({
141                     url: '{% url 'login' %}',
142                     type: 'POST',
143                     headers: {'X-CSRFToken': $.cookie('csrftoken')},
144                     data: {
145                         'username': username,
146                         'password': password,
147                         'cverification_code': cverification_code,
148  
149                     },
150                     success: function (request) {
151                         console.log(request);
152                         if (request.status === 1) {
153                             location.href = request.url;
154                         } else {
155                             $('#submit').next().text(request.url);
156                         }
157                     }
158                 })
159             }
160  
161         })
162     })
163 </script>
164 </html>
login.html

  index. Html

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>首页</title>
 6 </head>
 7 <body>
 8 <h1>index</h1>
 9 <a href="{%  url 'logout' %}"><h6>注销</h6></a>
10 <a href="{% url 'reset_psd' %}">修改密码</a>
11 </body>
12 </html>
login.html

  reset_psd.html

 1 {% load static %}
 2 <!DOCTYPE html>
 3 <html lang="en">
 4 <head>
 5     <meta charset="UTF-8">
 6     <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
 7     <title>修改密码</title>
 8 </head>
 9 <body>
10 <div><h3>当前用户:{{ username }}</h3>
11  
12         <p>请输入原密码:<input type="password" id="old_password"></p>
13         <P>请输入新密码:<input type="password" id="new_password"></P>
14         <p>请确认新密码:<input type="password" id="r_new_password"></p>
15         {% csrf_token %}
16         <p><button class="btn btn-success" id="submit">保存</button></p>
17  
18 </div>
19 </body>
20 <script src="{% static 'jquery-3.4.1.js' %}"></script>
21 <script src="{% static 'jquery-cookie-1.4.1.js' %}"></script>
22 <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>
23 <script>
24     $(function () {
25         $('#submit').click(function () {
26             var old_password=$('#old_password').val().trim();
27             var new_password=$('#new_password').val().trim();
28             var r_new_password=$('#r_new_password').val().trim();
29  
30             if(old_password===''||new_password==='' || r_new_password===''){
31                 alert('不允许有空!');
32                 return false
33             };
34  
35             if(new_password!==r_new_password){
36                 alert('两次输入的新密码不一致,请重新确认输入!');
37                 return false
38             };
39  
40  
41             $.ajax({
42                 url:'{% url "reset_psd" %}',
43                 type:'post',
44                 headers:{'X-CSRFToken':$.cookie('csrftoken')},
45                 data:{
46                     old_password:old_password,
47                     new_password:new_password,
48                     r_new_password:r_new_password,
49                 },
50                 success:function (response) {
51                     if(response.status===true){
52                         alert(response.info);
53                         location.href=response.url;
54                     }
55                     else {
56                         alert(response.info)
57                     }
58                 }
59  
60             }
61             )
62         })
63     })
64 </script>
65 </html>
reset_psd.html

 

posted @ 2019-07-21 23:38  笑得好美  阅读(503)  评论(0编辑  收藏  举报