登录,注册页面的验证码

1.Form表单的input中的type=buttontype=submit是有区别的:

Submit会直接提交表单数据,发送post请求

Button只是一个普通按钮

2.当用户认证组件中的字段不够我们使用时,可以自定义其他的字段

1 from django.contrib.auth.models import AbstractUser
2 class UserInfo(AbstractUser):
3             tel=models.CharField(max_length=32)

同时要配置settings文件:告诉Django哪个app下的哪个表

AUTH_USER_MODEL="app01.UserInfo"

此时原生的user表就变成了userinfo

3.如何给注册登录页面添加验证码

图片的处理要基于PIL模块,下载PIL模块,要下载包:pip3 install pillow

urls.py

 1 from django.contrib import admin
 2 from django.urls import path
 3 from app01 import views
 4 urlpatterns = [
 5     path('admin/', admin.site.urls),
 6     path('reg/', views.reg),
 7     path('login/', views.login),
 8     path('index/', views.index),
 9     path('get_valid_img/', views.get_valid_img),
10 ]

models.py

1 from django.contrib.auth.models import AbstractUser
2 class UserInfo(AbstractUser):
3     email=models.CharField(max_length=32)
4 
5 #向authform组件中的user表中增加其他字段,字段增加后的表名叫app01_userinfo

用户认证组件

1 class UserForm(forms.Form):
2     user=forms.CharField(min_length=5,label="用户名")
3     pwd=forms.CharField(min_length=5,label="密码")
4     r_pwd=forms.CharField(min_length=5,label='确认密码')
5     email=forms.EmailField(min_length=5,label="邮箱")

视图中的注册函数

 1 def reg(request):
 2     if request.method=="GET":
 3         form=UserForm()
 4         return render(request,"reg.html",locals())
 5     else:
 6         form=UserForm(request.POST)
 7         response_dic={"islogin":None}
 8         if form.is_valid():
 9             user=request.POST.get("user")
10             pwd=request.POST.get("pwd")
11             email=request.POST.get("email")
12             UserInfo.objects.create_user(username=user,password=pwd,email=email)
13             response_dic["islogin"]=True
14         else:
15             response_dic["islogin"] = False
16             error=form.errors
17             response_dic["error"] = error
18         return HttpResponse(json.dumps(response_dic))

注册HTML

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css">
 7 </head>
 8 <body>
 9 <div class="container">
10     <div class="row">
11         <div class="col-md-8 col-md-offset-2">
12         <h3>注册页面</h3>
13             <form action="">
14                 {% csrf_token %}
15                 {% for field in form %}
16                     <label for="">{{ field.label }}</label>
17                     {{ field }} <p class="error"></p>
18                 {% endfor %}
19                 <input type="button" class="btn btn-success login_btn" value="提交">
20             </form>
21         </div>
22     </div>
23 </div>
24 <script src="/static/js/jquery.js"></script>
25 <script>
26     $(".login_btn").click(function(){
27         $.ajax({
28             url:"",
29             type:"post",
30             data:{
31                 "user":$('#id_user').val(),
32                 "pwd":$("#id_pwd").val(),
33                 "r_pwd":$("#id_r_pwd").val(),
34                 "email":$("#id_email").val(),
35                 "csrfmiddlewaretoken":$("[name=csrfmiddlewaretoken]").val(),
36             },
37             success:function(response){
38                 response.is_login==true
39                 location.href="/login/"
40             }
41         })
42     })
43 </script>
44 </body>
45 </html>

登录视图需要用到的验证码视图

  1 def get_valid_img(request):
  2     # 方式一:读取指定的图片
  3     # with open("static/aaa.jpg","rb") as f:
  4     #     data=f.read()
  5 
  6     # 方式二:基于PIL模块,创建验证码图片
  7     # from PIL import Image
  8     # 1.创建图片
  9     # img=Image.new("RGB",(350,34),"yellow")
 10     # 原码部分:三个参数分别是模式,图片大小,背景色
 11     # def new(mode, size, color=0):
 12     # 颜色参数动态可以使用三原色
 13     # def get_do_color():
 14     #     import random
 15     #     return (random.randint(0,255),random.randint(0,255),random.randint(0,255))
 16     # img=Image.new("RGB",(350,34),get_do_color())
 17 
 18 
 19     # 2.生成图片
 20     # f=open("valid.png","wb")
 21     # img.save(f,"png")
 22     # 原码部分:fp是文件句柄 最后一个参数是文件格式,文件句柄就是文件存储的位置
 23     # def save(self, fp, format=None, **params):
 24     # with open("valid.png","rb") as f:
 25     #     data=f.read()
 26     # 每次都要放到磁盘中太浪费空间
 27 
 28     # 方式三:将图片存到内存中,对内存的控制需要io模块
 29     # from io import BytesIO
 30     # from PIL import Image
 31     # def get_do_color():
 32     #     import random
 33     #     return (random.randint(0,255),random.randint(0,255),random.randint(0,255))
 34     # img=Image.new("RGB",(350,34),get_do_color())
 35     # f=BytesIO()
 36     # 内存句柄,将文件存到内存中
 37     # img.save(f,"png")
 38     # data=f.getvalue()
 39     # 从内存中读取文件
 40 
 41 
 42     # 方式四:完善文本
 43     # from io import BytesIO
 44     # from PIL import Image ,ImageFont,ImageDraw #为图片添加内容需要引入画笔,ImageFont为创建字体对象
 45     # def get_do_color():
 46     #     import random
 47     #     return (random.randint(0,255),random.randint(0,255),random.randint(0,255))
 48     # img=Image.new("RGB",(350,34),get_do_color())
 49     # draw=ImageDraw.Draw(img)  #画笔需要一个参数作为画板
 50     # 构建字体对象
 51     # font=ImageFont.truetype("static/font/kumo.ttf",40)
 52     # draw.text((0,0),"aaaaaa",fill=get_do_color(),font=font)
 53     # text方法原码部分
 54     # def text(self, xy, text, fill=None, font=None, anchor=None, *args, **kwargs):
 55     # 画笔的text方法 xy参数为一个坐标元组,表示画在背景的哪里,text为需要画的内容,fill是画笔的颜色
 56     # font代表字体
 57 
 58     # 以下是图片的生成,文本部分添加在上面
 59     # f=BytesIO()
 60     # img.save(f,"png")
 61     # data=f.getvalue()
 62     # return HttpResponse(data)
 63 
 64     # 方式五
 65     import random
 66     from io import BytesIO
 67     from PIL import Image, ImageFont, ImageDraw
 68     def get_do_color():
 69 
 70         return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
 71 
 72     img = Image.new("RGB", (350, 34), get_do_color())
 73     draw = ImageDraw.Draw(img)
 74     font = ImageFont.truetype("static/font/kumo.ttf", 40)
 75     # 动态画背景上的内容
 76 
 77     content=""
 78     for i in range(6):
 79         random_num=str(random.randint(0,9))
 80         random_lower=chr(random.randint(97,122))
 81         random_upper=chr(random.randint(65,90))
 82         s=random.choice([random_num,random_lower,random_upper])
 83         i+=1
 84         draw.text((20+i*40,0), s, fill=get_do_color(), font=font)
 85         content=content+str(s)
 86     del request.session["content"]
 87     request.session["content"]=content
 88 
 89     # 加噪点噪线,让人能识别出来,机器识别不出来
 90     width = 350
 91     height = 34
 92     for i in range(5):
 93         x1 = random.randint(0, width)
 94         x2 = random.randint(0, width)
 95         y1 = random.randint(0, height)
 96         y2 = random.randint(0, height)
 97         draw.line((x1,y1,x2,y2),fill=get_do_color())
 98     for i in range(20):
 99         draw.point([random.randint(0,width),random.randint(0,height)],fill=get_do_color())
100         x=random.randint(0,width)
101         y=random.randint(0,height)
102         draw.arc((x,y,x+4,y+4),0,90,fill=get_do_color())
103 
104     f = BytesIO()
105     img.save(f, "png")
106     data = f.getvalue()
107     return HttpResponse(data)

登录视图

 1 def login(request):
 2     if request.method=="GET":
 3         return render(request,"login.html")
 4     else:
 5         user=request.POST.get("user")
 6         pwd=request.POST.get("pwd")
 7         yzm=request.POST.get("yzm")
 8         response={"user":None,"error_msg":""}
 9         if str(yzm).upper()==str(request.session.get("content")).upper():
10             user_obj=auth.authenticate(username=user,password=pwd)
11             if user_obj:
12                 response["user"]=user
13             else:
14                 response["error_msg"] = "用户名或密码错误"
15         else:
16             response["error_msg"]="验证码错误"
17         return HttpResponse(json.dumps(response))

登录的HTML

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>登录</title>
 6     <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css">
 7     <script src="/static/js/jquery.js"></script>
 8 </head>
 9 <body style="background-image: url('https://ss0.bdstatic.com/k4oZeXSm1A5BphGlnYG/skin/831.jpg?2')">
10     <div class="container" >
11         <dic class="row">
12             <div class="col-md-offset-2 col-md-8">
13                 <form action="">
14                     {% csrf_token %}
15                     <div class="form-group">
16                         <label for="">用户名</label>
17                         <input type="text" class="form-control" id="user">
18                     </div>
19 
20                     <div class="form-group">
21                         <label for="">密码</label>
22                         <input type="password" class="form-control" id="pwd">
23                     </div>
24 
25                     <div class="form-group">
26                         <label for="">验证码</label>
27                         <div class="row">
28                             <div class="col-md-6 col-sm-6 col-lg-6">
29                                 <input type="text" class="form-control" id="yzm">
30                             </div>
31                             <div class="col-md-6 col-sm-6 col-lg-6">
32                                 <img width="350" height="34" src="/get_valid_img/" alt="">
33                             </div>
34                         </div>
35                     </div>
36                     <p class="error"></p>
37                     <input type="button" value="提交" class="pull-right btn btn-success login_btn">
38                 </form>
39             </div>
40         </dic>
41     </div>
42 
43     <script>
44         $(".login_btn").click(function(){
45             $.ajax({
46                 url:"",
47                 type:"post",
48                 data:{
49                     "user":$("#user").val(),
50                     "pwd":$("#pwd").val(),
51                     "yzm":$("#yzm").val(),
52                     "csrfmiddlewaretoken":$("[name=csrfmiddlewaretoken]").val()
53                 },
54                 success:function(response){
55                     dic=JSON.parse(response);
56                     if(dic.user){
57                         location.href="/index/";
58                    }
59                     else{
60                         $(".error").val(dic.erroe_msg);
61                     }
62                 }
63 
64             })
65         })
66     </script>
67 </body>
68 </html>
  1. 在视图函数中,除了可以用request.method做分支的判断外,还可以用request.is_ajax()
  2. JsonResponse

引入:from django.http import JsonResponse

使用:return JsonResponse(dic)

作用:视图函数中不用每一次向前端传字典都Json了,前端通过ajax得到的response不用parse了

原因:查看源码

 1 class JsonResponse(HttpResponse):
 2     def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
 3                  json_dumps_params=None, **kwargs):
 4         if safe and not isinstance(data, dict):
 5             raise TypeError(
 6                 'In order to allow non-dict objects to be serialized set the '
 7                 'safe parameter to False.'
 8             )
 9         if json_dumps_params is None:
10             json_dumps_params = {}
11         kwargs.setdefault('content_type', 'application/json')

//原码中修改了响应头中的content_type,告诉浏览器以json的形式解码
        data = json.dumps(data, cls=encoder, **json_dumps_params)

//原码中帮我们做了序列化的工作
        super().__init__(content=data, **kwargs)

//并且传到了HttpResponse

Ajax的success在接收到response时,会先看响应头中有没有 content_type,如果有,按照格式解码,如果没有,直接放到response中

  1. 验证码的点击刷新

Img标签有一个独特的刷新方式,在路径(http://127.0.0.1:8000/get_valid_img/)后加问号就是获取新的图片,问号可以不止一个,所以验证码的点击刷新即为img标签绑定一个click事件

$("#img").click(function(){
         $(this)[0].src+="?"
})

  1. 笔记本的任务管理器可以查看,终止正在运行的程序
  2. Forms组件补充

如果组件中的每一个字段都有同样的约束,可以给该组件添加一个__init__ 方法,让其在继承父类__init__方法的同时,填加新的内容

def __init__(self,*args,**kwargs):
         super().__init__(*args,**kwargs)
        for filed in self.fields.values():
                filed.widget.attrs.update({"class":"form-control"})

  1. 全局错误可以不用放到__all__中

正常情况下的全局钩:会将全局错误放到__all__中

 1 Def clean(self):
 2 
 3 Pwd=seif.cleaned_data.get(“pwd”)
 4 
 5 R_pwd=eif.cleaned_data(“r_pwd”)
 6 
 7 If pew=r_pwd:
 8 
 9 Return self.cleaned_data
10 
11 Else:
12 
13 Raise ValidationError(“两次密码不一致”)
14 
15 让全局错误放到其他字段中:
16 
17 Def clean(self):
18 
19 Pwd=seif.cleaned_data.get(“pwd”)
20 
21 R_pwd=eif.cleaned_data(“r_pwd”)
22 
23 If pew=r_pwd:
24 
25 Return self.cleaned_data
26 
27 Else:
28 
29 Self.add_error(“r_pwd”, ValidationError(“两次密码不一致”))
原文地址:https://www.cnblogs.com/shanghongyun/p/9900807.html