• 登录,注册页面的验证码


    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(“两次密码不一致”))
  • 相关阅读:
    Node 12 值得关注的新特性
    vue实现PC端调用摄像头拍照人脸录入、移动端调用手机前置摄像头人脸录入、及图片旋转矫正、压缩上传base64格式/文件格式
    解决Vuex刷新页面数据丢失问题 ---- vuex-persistedstate持久化数据
    博客搬迁到 gitHub + hexo 去了, 博客园以后比较少更新
    Jenkins结合shell脚本实现(gitLab/gitHub)前端项目自动打包部署服务器
    GET 和 POST 的区别 以及为什么 GET请求 比 POST请求 更快
    Git常用命令及使用,GitLab/GitHub初探,Git/Svn区别
    pc端结合canvas实现简单签名功能
    N的阶乘末尾0的个数和其二进制表示中最后位1的位置
    实现一个动态存储分配
  • 原文地址:https://www.cnblogs.com/shanghongyun/p/9900807.html
Copyright © 2020-2023  润新知