登录功能

思路分析

登录页面,我们还是采用ajax的方式提交用户数据

唯一需要学习的是如何制作图片验证码!

具体的登录页面效果图如下:
image

如何制作图片验证码

推导步骤1:在img标签的src属性里放上验证码的请求路径

补充1.img的src属性:
	1.图片路径
	2.url
	3.图片的二进制数据
补充2:字体样式
	我们计算机上之所以可以输出各种各样的字体样式,其内部其实对应的是一个个以.ttf结尾的文件
	
由于img的src属性里可以放图片的二进制数据,因此我们可以在src里放上图片的请求路径,返回的是一个图片的二进制数据

<img src="/get_code/" alt="" width="350" height="35">

# 该视图函数返回的是图片的二进制数据,图片是本地已有的图片路径
def get_code(request):
    with open ('static/img/default.png','rb') as f:
        data = f.read()
    return HttpResponse(data)

字体样式网站

推导步骤2:利用pillow模块动态产生图片

"""
图片相关的模块:
        pip3 install pillow
导入:from PIL import Image,ImageDraw,ImageFont
Image:生成图片
ImageDraw:能够在图片上乱涂乱画
ImageFont:控制字体样式
"""
from PIL import Image,ImageDraw,ImageFont
import random

def get_random():
    return random.randint(0,255),random.randint(0,255),random.randint(0,255),

def get_code(request):
    1.先产生一个图片,new方法的第一个参数是固定模式RGB格式,第二个是图片大小(宽,高),第三个是图片颜色(可以放rgb模式的颜色)
    # image_obj = Image.new('RGB',(350,35),'green') # 固定颜色
    # image_obj = Image.new('RGB',(350,35),(23,43,53)) # 变形1
    image_obj = Image.new('RGB', (350, 35), get_random()) # 变形2
    2.将产生的图片存起来,打开一个文件,该图片有一个save方法可以存储图片,第一个参数是文件句柄,第二个是存储图片格式
    with open('xxx.png','wb') as f:
        image_obj.save(f,'png')

    3.再将图片以二进制形式读出来,返回给img标签的src属性
    with open('xxx.png','rb') as f:
        data = f.read()
    return HttpResponse(data)

上述方法:会进行频繁的文件存储IO操作,效率比较低下,步骤4利用内存管理器模块优化!

推导步骤4:利用内存管理器模块优化

"""
导入内存管理器模块:from io import BytesIO,StringIO
BytesIO:功能临时帮您存储数据,返回的数据是二进制
StringIO:功能临时帮您存储数据,返回的数据是字符串
"""
def get_code(request):

    # 1.同样先生成一个图片对象
    image_obj = Image.new('RGB', (350, 35), get_random())
    # 2.这里再生成一个内存管理器对象,就可以看成是f文件句柄
    io_obj = BytesIO()
    # 3.将图片保存到文件管理器对象里
    image_obj.save(io_obj,'png')
    # 4.把图片从文件管理器对象里取出来,用getvalue()方法
    return HttpResponse(io_obj.getvalue())

最终步骤:写图片验证码

def get_code(request):
    # 1.同样先生成一个图片对象
    image_obj = Image.new('RGB', (350, 35), get_random())
    # 2.在图片上生成一个画笔对象
    img_draw = ImageDraw.Draw(image_obj)
    # 3.设置字体样式,truetype()第一个参数是字体样式路径,第二个是字体大小
    img_font = ImageFont.truetype('static/font/222.ttf',30)

    # 4.随机生成验证码,五位,大小写字母、数字
    code = ''
    for i in range(5):
        random_upper = chr(random.randint(65,90)) # 65-90的数字使用chr()函数对应转成大写字母
        random_lower = chr(random.randint(97,122)) # 97-122的数字使用chr()函数对应转成小写字母
        random_int = str(random.randint(0,9))

        # 从上面三种随机选择一种
        tmp = random.choice([random_int,random_lower,random_upper])
        # 将产生的随机字符串写到图片上
        """
        text()方法的第一个参数,字符串在图片上的坐标,第二个是字符串,
        第三个字符串的颜色,第四个字体样式和大小
        """
        img_draw.text((i*60,0),tmp,get_random(),img_font)
        code += tmp
    print(code)
    # 5.将生成的随机验证码保存起来,因为在登录的视图函数需要用到,进行比对
    request.session['code'] = code
    # 6.再生成一个内存管理器对象,就可以看成是f文件句柄
    io_obj = BytesIO()
    # 7.将图片保存到文件管理器对象里
    image_obj.save(io_obj,'png')
    # 8.把图片从文件管理器对象里取出来,用getvalue()方法
    return HttpResponse(io_obj.getvalue())

补充

如何让用户一点验证码图片就刷新验证码

<img src="/get_code/" alt="" width="350" height="35" id="img">


<script>
    $('#img').click(function (){
        let OldUrl = $(this).attr('src')
        $(this).attr('src',OldUrl += '?')
    })
</script>

向后端提交用户登录数据

前端:

    // 点击登录按钮向后端发送ajax请求
    $('#commit').click(function (){
        $.ajax({
            type:'post',
            url:'',
            data:{
                'username': $('#id_username').val(),
                'password': $('#id_password').val(),
                'code': $('#id_code').val(),
                'csrfmiddlewaretoken': '{{ csrf_token }}',
            },
            success:function (args){
                if (args.code==1000){
                    window.location.href = args.url
                }else {
                    $('#error').text(args.msg)
                }
            }
        })
    })

后端:

# 二、登录页面
def login(request):
    # 1.判断是否为ajax请求
    if request.method == 'POST':
        back_dic = {'code':1000,'msg':''}
        # 2.获取用户提交的登录数据
        username = request.POST.get('username')
        password = request.POST.get('password')
        code = request.POST.get('code')
        # 3.判断验证码是否正确
        if code.upper() == request.session['code'].upper():
            # 4.利用auth模块判断用户名和密码是否正确
            user_obj = auth.authenticate(request,username=username,password=password)
            if user_obj:
                # 5.正确则保存用户状态
                auth.login(request,user_obj)
                # 6.跳转到主页
                back_dic['url'] = '/home/'
            else:
                # 7.错误信息展示
                back_dic['code'] = 1001
                back_dic['msg'] = '用户名或者密码不正确'
        else:
            back_dic['code'] = 1002
            back_dic['msg'] = '验证码不正确'
        return JsonResponse(back_dic)
    return render(request,'login.html',locals())

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:登录功能 - Python技术站

(0)
上一篇 2023年4月2日 下午4:48
下一篇 2023年4月2日 下午4:48

相关文章

  • 权限类与频率类

    权限类 主要用途:用户登录了,某个接口可能只有超级管理员才能访问,普通用户不能访问 案列:出版社的所有接口,必须登录,而且是超级管理员才能访问 分析步骤 第一步:写一个类,继承BasePermission 第二步:重写has_permission方法 第三步:在方法校验用户时候有权限(request.user就是当前登录用户) 第四步:如果有权限,返回Tru…

    2023年4月2日
    00
  • 文章详情页制作

    url的设计 /usrname/article/1 /用户名/article/文章主键值 re_path(r’^(?P<username>\w+)/article/(?P<article_id>\d+)/$’,views.article_detail,name=’detail’), 视图函数的设计 # 七、文章详情页 def arti…

    Python开发 2023年4月2日
    00
  • 线程

    1. 什么是线程 线程就是进程里面的执行单位,每一个进程肯定都自带一个线程,真正被cpu执行的是线程,线程是代码的执行过程,该过程中需要的资源都找对应的进程要 进程是资源的单位,线程是执行单位! 补充:同一个进程里面的多个线程资源是共享的! 2. 为啥要有线程 一个进程里面可以开设多个线程,而开设线程是不需要申请内存空间的(进程需要),因此,开设线程的消耗远…

    2023年4月2日
    00
  • for循环语法

    for循环 for循环常用来遍历取值! for循环的基本语法 for 变量名 in 可迭代对象: 代码1 代码2 … # 可迭代对象可以是字典、列表、字符串、元组、集合 for + range range是用来控制for循环次数的方法 for i in range(1,9): print(‘====’) # range(1,9)循环1-8次,括号是顾头不…

    Python开发 2023年4月2日
    00
  • 基础数据类型之数字和字符串

    1.数字类型 数字类型的数据可以相互的进行+-/*、也可以进行相互的比较(<>=) 1.1整型int age = 18 记录年龄等整数 print(type(age))# int类型 int()方法可以将其他类型的数据转换成int类型 1.1.2二、八、十六进制的相互转换 1.十进制《—》二进制 # bin()方法 print(bin(11)…

    Python开发 2023年4月2日
    00
  • 函数的递归

    1.函数的递归的定义 函数的递归调用:是函数嵌套调用的一种特殊形式 具体是指:在调用一个函数的过程中又直接或者间接的调用到本身,是一个死循环,最大递归是1000次,超出之后报错。 2.函数递归的调用 # 直接调本身 def f1(): print(‘是我还是我’) f1() f1() # 间接调用 def f1(): print(‘f1’) f2() def…

    Python开发 2023年4月2日
    00
  • 基础数据类型之字典

    1.字典的定义 使用{}定义字典,括号内用逗号分隔开多个key:value,其中value可以是任意类型,但是key必须是不可变类型且不能重复,是无序的! info=[ [‘name’,’zhang’], (‘age’,19) [‘gender’,’男’] ] d={} # 第一种方式定义 d=dict(x=1,y=2) #第二种,dict里面也可以穿一个i…

    Python开发 2023年4月2日
    00
  • django中操作mysql数据库

    1.准备工作(django连接数据库) 1.本机电脑下载好mysql数据库2.打开django,修改setting.py中的DATABASES配置项 DATABASES = { ‘default’: { ‘ENGINE’: ‘django.db.backends.mysql’, ‘NAME’: ‘python’, ‘USER’: ‘root’, ‘PASSW…

    2023年4月2日
    00
合作推广
合作推广
分享本页
返回顶部