Loading

BBS(仿博客园系统)项目02(登录(动态生成验证码)、主页搭建)

一、登录功能实现: 

html页面:

①login.html页面:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="/static/reg.css">
</head>
<body>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-6 col-md-offset-3
                    col-sm-6 col-sm-offset-3
                    col-xs-8 col-xs-offset-2">
            <h2 class="text-center">登录页面</h2>
            <hr>
            {% csrf_token %}
            <div class="form-group">
                <label for="id_username">用户名</label>
                <input type="text" id="id_username" name="username" class="form-control">
            </div>
            <div class="form-group">
                <label for="id_password">密码</label>
                <input type="password" id="id_password" name="password" class="form-control">
            </div>
            <div class="form-group">
                <label for="id_code">验证码</label>
                    <div class="row">
                        <div class="col-md-6
                                    col-sm-4
                                    col-xs-4">
                            <input type="text" id="id_code" name="code" class="form-control">
                        </div>
                        <div class="col-md-6
                                    col-sm-8
                                    col-xs-8">
                            <div class="col-md-7 col-sm-7 col-xs-7">
{#                                验证码图片有后端生成,通过路由获取,宽度自适应,高度固定#}
                                <img src="/get_code/" width="100%" height="60" id="id_code_img">
                            </div>
                            <div class="col-md-5 col-sm-5 col-xs-5">
                                <span>看不清?点击图片换一张</span>
                            </div>

                        </div>
                    </div>
            </div>
            <button class="btn btn-primary" id="id_submit">登录</button>
{#            此处显示错误提示,has-error是为了设置样式而设的类#}
            <span class="has-error" id="id_error"></span>
        </div>
    </div>
</div>
<script>
    // 验证码图片被点击,就在该src后面自动拼接一个问号?,后端只要发现路由有变化就会重新生成验证码图片
    $('#id_code_img').on('click',function () {
        let old_path = $(this).attr('src');
        $(this).attr('src',old_path+'?')
    });
    // 使用ajax提交数据,动态刷新login页面局部信息
    $('#id_submit').on('click',function () {
        $.ajax({
            url: '',
            type: 'post',
            data: {
                'username':$('#id_username').val(),
                'password':$('#id_password').val(),
                'code':$('#id_code').val(),
                'csrfmiddlewaretoken': $('[name="csrfmiddlewaretoken"]').val(),
                //也可以使用这个
                {#'csrfmiddlewaretoken': '{{ csrf_token }}',#}  
            },
            success:function (data) {
                // 登录成功
                if (data.code==100){
                    location.href = data.url
                }
                // 登录失败,将error的span标签加上内容
                else {$('#id_error').html(data.msg)}
            }

        })
    })
</script>
</body>
</html>
②set_password.html页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>BBS</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="/static/reg.css">
</head>
<body>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <h2 class="text-center">修改密码</h2>
            <hr>
            <form action="" method="post">
                {% csrf_token %}
                <div class="form-group">
                    <label for="id_username">用户名</label>
                    <input type="text" class="form-control" name="username" id="id_username" disabled value="{{ request.user.username }}">
                </div>
                <div class="form-group">
                    <label for="id_old_password">原密码</label>
                    <input type="password" class="form-control" name="old_password" id="id_old_password">
                    <span class="has-error" id="id_old_password_error">{{ old_password_error }}</span>
                </div>
                <div class="form-group">
                    <label for="id_password">密码</label>
                    <input type="password" class="form-control" name="password" id="id_password">
                </div>
                <div class="form-group">
                    <label for="id_confirm_password">确认密码</label>
                    <input type="password" class="form-control" name="confirm_password" id="id_confirm_password">
                    <span class="has-error" id="id_confirm_password_error">{{ confirm_password_error }}</span>
                </div>
                <div class="form-group">
                <button class="btn btn-primary" id="id_submit">提交修改</button>
                </div>
            </form>
        </div>
    </div>
</div>
<script>
    $('input').on('focus',function () {
        $(this).next().html('')
    })
</script>
</body>
</html>
③home.html页面(导航条搭建)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>主页</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
</head>
<body>
<nav class="navbar navbar-default">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                    data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">BBS</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <li class="active"><a href="#">文章 <span class="sr-only">(current)</span></a></li>
                <li><a href="#">随笔</a></li>
            </ul>
            <ul class="nav navbar-nav navbar-right">
                {% if request.user.is_authenticated %}
                <li><a href="">欢迎您</a></li>
                <li><a href="#">{{ request.user.username }}</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                       aria-expanded="false">更多操作 <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="/set_password/">密码修改</a></li>
                        <li><a href="#">修改头像</a></li>

                        <li role="separator" class="divider"></li>
                        <li><a href="/logout/">注销</a></li>
                    </ul>
                </li>
                {% else %}
                    <li><a href="/login/">登录</a></li>
                    <li><a href="/register/">注册</a></li>
                {% endif %}
            </ul>
        </div><!-- /.navbar-collapse -->
    </div><!-- /.container-fluid -->
</nav>
<div class="container-fluid">
    <div class="row">

    </div>

</div>
</body>
</html>
主页面导航条搭建
④css样式文件
#myform span {
    color: red;
}

.has-error {
    color: red;
}

views.py视图函数

①随机验证码生成:
# 随机生成颜色代码
def get_random():
    return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)

# 从PIL(需下载)导入Image用来生成图片,ImageDraw在图片上写字,ImageFont图片上的字体样式
from PIL import Image,ImageDraw,ImageFont,ImageFilter
from io import BytesIO  # 帮我们保存数据,同时取得时候以二进制形式返回给我

# 随机生成验证码图片
def get_code(request):
    # 推导步骤1,打开本地文件发送二进制数据给前端传code图片
    '''
    with open(r'D:\Django\BBS01\app01\static\avatar\code1.jpg', 'rb') as f:
        data = f.read()
    return HttpResponse(data)
    '''
    # 推导步骤2,生成动态图片发送二进制数据
    ''''
    # img_obj = Image.new('RGB', (180, 35), 'red')
    # img_obj = Image.new('RGB', (180, 60), (128, 128, 128))
    img_obj = Image.new('RGB', (180, 60), get_random())
    # 先保存成文件
    with open('demo.png', 'wb') as f1:
        img_obj.save(f1)
    with open('demo.png', 'rb') as f2:
        return HttpResponse(f2.read())
    '''
    # 推导步骤3,图片存放不再依赖于文件的形式
    '''
    img_obj = Image.new('RGB', (180, 60), get_random())
    ## 生成一个BytesIO对象
    io_obj = BytesIO()  # 可以当做一个文件句柄f使用
    img_obj.save(io_obj, 'png')  # 将生成的图片数据存入内存管理器中,注意后面要指定图片后缀名
    return HttpResponse(io_obj.getvalue())
    # 通过io_obj.getvalue()来取出,取出的是二进制形式数据
    '''
    # 最后在图片上‘画’上字母和数字
    img_obj = Image.new('RGB', (180, 60), get_random())
    # 生成一个画笔对象
    img_draw = ImageDraw.Draw(img_obj)
    # 生成一个字体对象
    img_font = ImageFont.truetype('app01/static/code2.ttf', 48)
    # 随机验证码:数字+字母
    # 先定义一个code变量来记录生成的码,用于后面的校验
    code = ''
    for i in range(4):
        number = str(random.randint(0, 9))
        upper = chr(random.randint(97, 122))
        lower = chr(random.randint(65, 90))
        temp_code = random.choice([number, upper, lower])
        # 将随机的码写到图片上:
        img_draw.text((20+i*38, 10), temp_code, get_random(), img_font)
        #                坐标位置  随机生成的码  随机生成的颜色 码的字体样式
        # 注意这里需要一个字一个字的往图片里写码,每次写坐标要向右移动,这样码才不会叠加在一起
        code += temp_code
    # 此时img_obj图片对象里面就包含了4个随机码
    print(code)
    # 将code字符串存入session中,用于后面登录的校验
    request.session['code'] = code
    # 生成一个io对象帮助我们动态存随机生成的图片
    io_obj = BytesIO()
    # 设置图片模糊(了解)
    # img_obj = img_obj.filter(ImageFilter.BLUR)
    img_obj.save(io_obj, 'png')  # 将图片对象保存到io对象中
    return HttpResponse(io_obj.getvalue())
②登录相关视图函数,包括登录、注销、设置密码、主页简单搭建
# 登录
def login(request):
    back_dic = {'code': 100, 'msg': ''}
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        code = request.POST.get('code')
        # 先校验验证码是否输入正确
        if request.session.get('code').lower() == code.lower():
            # 通过auth.authenticate()方法,对用户进行认证
            user_obj = auth.authenticate(username=username, password=password)
            if user_obj:
                # 如果user_obj存在,则说明用户名和密码正确,即表示登录成功
                auth.login(request, user_obj)  # 记录登录状态
                back_dic['msg'] = '登录成功'
                back_dic['url'] = '/home/'
            else:
                back_dic['code'] = 102
                back_dic['msg'] = '用户名或密码错误'
        else:
            back_dic['code'] = 101
            back_dic['msg'] = '验证码错误'
        return JsonResponse(back_dic)
    return render(request, 'login.html')

# 注销
def logout(request):
    auth.logout(request)
    return redirect('/home/')

# 主页
def home(request):
    return render(request, 'home.html')

# 修改密码
from django.contrib.auth.decorators import login_required
@login_required
def set_password(request):
    if request.method == 'POST':
        old_password = request.POST.get('old_password')
        password = request.POST.get('password')
        confirm_password = request.POST.get('confirm_password')
        if request.user.check_password(old_password):  # 如果密码检查通过
            if password == confirm_password:
                request.user.set_password(password)
                request.user.save()
                return redirect('/login/')
            else:
                return render(request, 'set_password.html', {'confirm_password_error': '密码输入不一致'})
        else:
            return render(request, 'set_password.html', {'old_password_error': '原密码错误'})

    return render(request, 'set_password.html')

 其它相关配置

# 路由urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^register/', views.register),
    url(r'^login/', views.login),
    url(r'^get_code/', views.get_code),
    url(r'^home/', views.home),
    url(r'^logout/', views.logout),
    url(r'^set_password/', views.set_password),
]

# 配置文件settings.py
# 设置默认跳转登录路由
LOGIN_URL = '/login/'

 

posted @ 2019-06-20 22:49  MrSu  阅读(675)  评论(0编辑  收藏  举报