第四节: 登陆功能

登陆功能

本功能需求:

-使用Ajax提交数据信息

-渲染用户名密码不符合要求的错误信息

-登陆后可以实现登出当前账号

拓展需求:

-登陆时判断用户是否被冻结

-登陆时使用登陆表单进行验证

一、添加路由

在urls.py中添加

1、登陆路由

    path('login/', views.login, name='login'),

2、生成随机验证码路由

    path('get_valid_code/', views.get_valid_code, name='get_valid'),

3、登出当前用户路由

    path('logout/', views.logout, name='logout'), 

二、添加视图函数

在views.py中

1、先导入一些需要的模块

from django.contrib import auth
from django.contrib.auth import authenticate

2、然后添加视图函数login

def login(request):
    if request.method == 'POST':
        res = {'code': 100}
        username = request.POST.get('username')
        password = request.POST.get('password')
        valid_code = request.POST.get('valid_code')
        if request.session.get('valid_code').upper() == valid_code.upper() or valid_code == '123':
            user = auth.authenticate(username=username, password=password)
            freezed = models.UserInfo.objects.filter(username=username, is_active=0).first()
            res['url'] = '/index/'
            if freezed:
                res['code'] = 105
                res['msg'] = '账户被冻结'
            if user:
                auth.login(request, user)
                res['msg'] = '登录成功'
            else:
                res['code'] = 101
                res['msg'] = '用户名密码错误'
        else:
            res['code'] = 102
            res['msg'] = '验证码错误'
        return JsonResponse(res)
    elif request.method == 'GET':
        form = x_forms.FormLogin()
        return render(request, 'Login.html', {'form': form})
    else:
        return HttpResponse('非法请求!')

其中涉及到一个手动添加登录验证码的操作

添加视图函数get_rgb(随机函数,利用RGB形成随机颜色)

和get_valid_code(获取随机验证码)

def get_rgb():
    return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)
def get_valid_code(request):
    img = Image.new('RGB', (200, 38), get_rgb())
    img_draw = ImageDraw.Draw(img)
    img_font = ImageFont.truetype('./static/font/FZFenSTXJW.TTF', 25)
    valid_code = ''
    for i in range(5):
        low_char = chr(random.randint(97, 122))
        num_char = random.randint(0, 9)
        upper_char = chr(random.randint(65, 90))
        res = random.choice([low_char, num_char, upper_char])
        valid_code += str(res)
        img_draw.text((i * 40 + 10, 5), str(res), get_rgb(), img_font)
    request.session['valid_code'] = valid_code
    print(valid_code)

    f = BytesIO()
    img.save(f, 'png')
    data = f.getvalue()
    return HttpResponse(data) 

(拓展)我们可以在x_forms,py的文件中加入一个表示登陆信息校验的类(FormLogin),用来校验登陆时从前端返回的字符串是否符合要求

class FormLogin(forms.Form):
    username = forms.CharField(
        required=True,
        label='<i class="fa fa-user width-30" aria-hidden="true"></i>',
        error_messages={
            'required': '用户名不能为空'
        },
        widget=widgets.TextInput(attrs={'class': 'form-control', 'placeholder': '请输入账号'}),
    )
    password = forms.CharField(
        required=True,
        label='<i class="fa fa-lock width-30" aria-hidden="true"></i>',
        error_messages={
            'required': '密码不能为空'
        },
        widget=widgets.PasswordInput(attrs={'class': 'form-control', 'placeholder': '请输入密码'}),
    )

3、添加登出视图函数(logout)

def logout(request):
    auth.logout(request)
    return redirect(reverse('login'))

(拓展): 验证码暗门

这里的代码中

if request.session.get('valid_code').upper() == valid_code.upper() or valid_code == '123':

最后的123设置为方便开发者自己调试程序时使用,无论生成的随机验证码是什么,输入验证码123都可登陆,正式上线的话应该去除这个暗门

三、登录功能涉及的模型层操作

判断用户登录时使用扩写的UserInfo表中自带认证auth模块

user = authenticate(username=username, password=password)

(拓展)此处继承的原始User表中有个is_active字段,可以用来判断用户是否被冻结

freezed = models.UserInfo.objects.filter(username=username, is_active=0).first()

四、登录功能前端模板

1、在templates中的login.html中

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>登陆界面</title>
    {% include 'template_static/css_base.html' %}
    <style>
        ul {
            list-style: none
        }
    </style>
</head>
<body>
<div class="container-fluid">
    <div class="mt-5 mb-5"><br></div>
    <div class="row mt-5 mb-5">
        <div class="col-md-6 offset-md-3 card bg-white shadow-sm mr-3 my-img">
            <div class="row">
                <div class="col-md-8 card-body p-5 bg-white-7">
                    <div class="mt-5 mb-5"><br></div>
                    <h1 class="text-center mt-5 swiper-cube-shadow">欢迎回来</h1>
                    <form action="" method="post" class="mx-5 my-3">
                        {% csrf_token %}
                        {% for foo in form %}
                            <div class="input-group mt-2">
                                <div class="height-40 width-b100">
                                    <div class="input-group-prepend">
                                        <div class="input-group-text">
                                            <label for="{{ foo.auto_id }}" class="mb-0">{{ foo.label|safe }}</label>
                                        </div>
                                        {{ foo }}
                                    </div>
                                </div>
                            </div>
                        {% endfor %}
                        <div class="input-group mt-2">
                            <div class="input-group-prepend">
                                <div class="input-group-text radius-5">
                                    <i class="fa fa-hand-o-right width-30" aria-hidden="true"></i>
                                </div>
                            </div>
                            <input type="text" class="form-control radius-5" id="valid_code" name="password"
                                   placeholder="请输入验证码">
                            <img src="/get_valid_code/" height="38" width="200" id="valid_code_img"
                                 class="ml-1 radius-5 pointer" title="点击刷新验证码">
                        </div>
                        <input type="button" class="btn btn-outline-primary btn-block mt-3 mb-5" value="登录" id="btn-login">
                    </form>
                    <div class="mt-5 mb-3"><br><br></div>
                </div>
                <div class="col-md-4 bg-black-4">
                    <div class="h-100 pt-5 text-center">
                        <h2 class="text-white ml-3 mt-5">还未注册?</h2>
                        <p class="text-white mb-5">立即注册,观看更多内容!</p>
                        <div class="mt-5 mb-5"><br><br><br><br><br><br></div>
                        <a href="{% url 'register' %}" class="btn btn-outline-light">去注册</a>
                    </div>
                </div>
            </div>
        </div>
        <div class="alert alert-warning ml-5 col-md-2 shadow-sm invisible max-height-240" id="tips">
            <h4 class="alert-heading">温馨提示:</h4>
            <hr>
            <div class="d-none font-weight-bold m-3" id="tips1"></div>
            <div class="d-none font-weight-bold m-3" id="tips2"></div>
            <div class="d-none font-weight-bold m-3" id="tips3"></div>
        </div>
    </div>
</div>
<script>
    $('#valid_code_img').click(function () {
        var url = $("#valid_code_img")[0].src
        $("#valid_code_img")[0].src = url + '?'
    })
    $('#btn-login').click(function () {
        $('input').addClass('is-valid')
        if ($('#id_username').val().length === 0) {
            $('#id_username').removeClass('is-valid').addClass('is-invalid')
            $('#tips').removeClass('invisible')
            $("#tips1").text('请输入用户名').removeClass('d-none')
            setTimeout(function () {
                $('#tips').addClass('invisible')
                $('#id_username').removeClass('is-invalid').val('')
            }, 1500)
        }
        $('#id_password').addClass('is-valid')
        if ($('#id_password').val().length === 0) {
            $('#id_password').removeClass('is-valid').addClass('is-invalid')
            $('#tips').removeClass('invisible')
            $("#tips2").text('请输入密码').removeClass('d-none')
            setTimeout(function () {
                $('#tips').addClass('invisible')
                $('#id_password').removeClass('is-invalid').val('')
            }, 1500)
        }
        $.ajax({
            url: '/login/',
            method: 'post',
            data: {
                'username': $('#id_username').val(),
                'password': $('#id_password').val(),
                'valid_code': $('#valid_code').val(),
                'csrfmiddlewaretoken': $('[name="csrfmiddlewaretoken"]').val()
            },
            success: function (data) {
                console.log(data.url)
                if (data.code === 100) {
                    swal({
                        title: data.msg,
                        text: '正在为您跳转页面',
                        type: "success",
                        timer: 1500,
                        showConfirmButton: false,
                    })
                    setTimeout(function () {
                        location.href = data.url
                    }, 1500)
                } else if (data.code === 101) {
                    $('#tips').removeClass('invisible')
                    $("#tips1").text(data.msg).removeClass('d-none')
                    $('#id_username').removeClass('is-valid').addClass('is-invalid')
                    $('#id_password').removeClass('is-valid').addClass('is-invalid')
                    setTimeout(function () {
                        $('#tips').addClass('invisible')
                        $('#id_username').removeClass('is-invalid').val('')
                        $('#id_password').removeClass('is-invalid').val('')
                    }, 1500)
                } else if (data.code === 102) {
                    $('#tips').removeClass('invisible')
                    $("#tips3").text(data.msg).removeClass('d-none')
                    $('#valid_code').addClass('is-invalid')
                    setTimeout(function () {
                        $('#tips').addClass('invisible')
                        $('#valid_code').removeClass('is-invalid').removeClass('is-valid').val('')
                    }, 1500)
                }
            }
        })
    })
    $('#id_username').blur(function () {
        $('#id_username').addClass('is-valid')
        if ($('#id_username').val().length === 0) {
            $('#id_username').removeClass('is-valid').addClass('is-invalid')
            $('#tips').removeClass('invisible')
            $("#tips1").text('请输入用户名').removeClass('d-none')
            setTimeout(function () {
                $('#tips').addClass('invisible')
                $('#id_username').removeClass('is-invalid').val('')
            }, 1500)
        }
    })
    $('#id_password').blur(function () {
        $('#id_password').addClass('is-valid')
        if ($('#id_password').val().length === 0) {
            $('#id_password').removeClass('is-valid').addClass('is-invalid')
            $('#tips').removeClass('invisible')
            $("#tips2").text('请输入密码').removeClass('d-none')
            setTimeout(function () {
                $('#tips').addClass('invisible')
                $('#id_password').removeClass('is-invalid').val('')
            }, 1500)
        }
    })
    $('#valid_code').blur(function () {
        if ($('#valid_code').val().length === 0) {
            $('#valid_code').addClass('is-invalid')
            $('#tips').removeClass('invisible')
            $("#tips3").text('请输入验证码').removeClass('d-none')
            setTimeout(function () {
                $('#tips').addClass('invisible')
                $('#valid_code').removeClass('is-invalid').val('')
            }, 1500)
        }
    })

</script>
</body>
</html>
上一篇
下一篇
Copyright © 2022 Egon的技术星球 egonlin.com 版权所有 沪ICP备2022009235号 沪公网安备31011802005110号 青浦区尚茂路798弄 联系方式-13697081366