登陆功能
本功能需求:
-使用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>