700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Django实战【三】—用户登录 注册实现

Django实战【三】—用户登录 注册实现

时间:2019-05-29 07:49:38

相关推荐

Django实战【三】—用户登录 注册实现

一、项目前端模板的套用

1.为什么使用前端模板

因为我们开发ObCRM系统使用的是Django项目,而我们知道,Django框架是一个全面的重量级的框架,并不是全后端分离的,所以涉及到的页面需要我们用到前端的知识,但是我们并不是专业的前端工程师,很多页面的搭建对我们说还是有点吃力。

其实在很多实际工作中开发,前端页面都是通过网络上寻找相应的模板,这样就可以避免在前端样式上调整的时间浪费,我们只需要继承别人写好的模板文件来快速开发自己的前端页面,专心投入自己的后端开发代码中。

2.admin前端模板

刚我们说使用别人写好的模板文件,有利于我们快速开发项目;我们写的这个项目也是使用了git上一个开源的前端模板,大家可以去git搜索adminLTE,如果你没有用过,点击这里/ColorlibHQ/AdminLTE,将代码下载到本地就可以愉快的使用了。

我们解压后得到一个AdminLTE-master文件夹,文件夹路径结构如下:

目录下的文件内容如上,一般比较规范的模板文件,核心的js和css代码会放在dist路径下。

首先,我们先配置项目使用的静态文件夹,在项目路径下新建statics文件夹,settings中配置静态文件的路径,

STATIC_URL = '/static/'STATICFILES_DIRS = [ # 项目静态文件的配置os.path.join(BASE_DIR,"statics")]

其实我们使用模板文件就是使用它的核心js和css以及对应写好的html页面,我们这个项目中使用了adminLTE的一些其他html页面,也就是说还需要使用bowser_components、plugins文件,这里我就将这三个文件拷贝到statics下的新建adminlte文件夹下。

如下是我这个项目的静态文件目录结构

adminlte:用于存放模板的js和css文件bootstrap:存放的bootstrap核心js和cssjquery:存放jquery文件css:自己根据具体需求写的一些css文件js:自己根据具体需求写的一些js文件font:项目用到的字体文件

二、登录页面的实现

1.初始超级用户

还记得我们的ObCRM系统的用户表使用是django项目中user的扩展表把,为什么使用Django用户提供的user表来扩展呢?是因为我们想要使用Django框架内置的auth认证模块,auth认证模块可以密文存储用户密码,快速简便的查询用户信息进行验证。

auth模块知识点回顾点这里!:Django框架—auth认证模块

在实现登录功能之前,我们先要有一个用户账号,就作为我们项目的超级管理帐号把。创建账号的时候要注意,不能直接在数据库添加记录,因为这样账号密码是明文存储的。

创建超级用户的方式,是在django的manage环境下,执行如下命令

createsuperuser # 要通过这个指令来创建用户,因为这个指令会将你的密码加密

我们创建一个超级用户,这里我创建的用户帐号密码:ryxiong,ryxiong520

2.登录页面实现

登录url设置

因为我么项目涉及到多应用,所以需要使用到路由分发,用户登录输入rbac应用,所以我们在项目下url设置路由分发,将用户登录的url分发到rbac应用下。

urlpatterns = [url(r'^admin/', admin.site.urls),url(r'^rbac/', include("rbac.urls")),url(r'^customer/', include("customer.urls")),url(r'^education/', include("education.urls")),]

rbac应用下创建urls.py

注意:我们项目中实现验证码登录的功能,所以配置登录url还需要配置验证码url

from django.conf.urls import url,includefrom rbac.views import accounturlpatterns = [# 用户登录urlurl(r'^login/', account.Login.as_view(), name="login"),# 验证码urlurl(r'^get_auth_img/', account.GetAuthImg.as_view(), name="get_auth_img"),]

视图函数

对于登录用到的验证码获取我单独提炼了一个文件,放在rbac应用下的utils文件中的auth_code.py文件

get_authcode_img函数的作用是生成随机字符串,并通过内存操作符中读取出来,存储在session中,这样每个用户就可以根据携带自己的用户验证码请求后端,而不会和别人的验证码冲突。

import osimport stringimport randomfrom io import BytesIOfrom PIL import Image,ImageDraw,ImageFontfrom ObCRM import settings # 项目中的settings文件,配置了BASEDIR路径,在这里无需关注def get_authcode_img(request):"""获取随机验证码,带干扰噪点,:param request: request请求,用于将验证码存放在session中:return: 返回验证码图片的数据内容"""def get_background_color(): # 定义一个获取图片背景/噪点颜色的函数,产生浅色color = tuple((random.choices(range(160,256),k=3)))return colordef get_content_color(): # 定义一个获取文字颜色的函数,产生深色color = tuple((random.choices(range(0,100),k=3)))return colorimg_obj = Image.new("RGB",(117,34),get_background_color()) # 创建一个图片对象draw_obj = ImageDraw.Draw(img_obj) # 通过图片对象生成一个画笔对象font_path = os.path.join(settings.BASE_DIR,"statics","font","cerepf__.ttf") # 获取字体,注意有些字体无法显示数字font_obj = ImageFont.truetype(font_path,32) # 创建一个字体对象random_code = '' # 用户验证的字符串all_char = string.ascii_letters+string.digitsfor i in range(4):a = random.choice(all_char)random_code += adraw_obj.text((22,-3),random_code,fill=get_content_color(),font=font_obj)width = 117height = 34# 添加噪线for i in range(5): # 添加5条干扰线# 两个坐标点确定一条线x1 = random.randint(0,width)y1 = random.randint(0,height)x2 = random.randint(0,width)y2 = random.randint(0,height)draw_obj.line((x1,y1,x2,y2),fill=get_background_color()) # 画噪线# 添加噪点for i in range(30):draw_obj.point((random.randint(0,width),random.randint(0,height)),fill=get_background_color())f = BytesIO() # 生成内存操作符-句柄img_obj.save(f,"png") # 将图片存在内存中data = f.getvalue()# 获取句柄中的内容# # 存验证码方式:1.存在全局变量(不可取,多个用户会顶替)2.存在各自客户的session中# # 方式1# global valid_str# valid_str = random_code# 方式二,推荐request.session["authcode"] = random_codereturn data

rbac视图文件,我们在应用下创建了views文件夹,文件中新建account来处理帐号相关的视图。

from django import viewsfrom django.contrib import authfrom django.http import JsonResponsefrom django.shortcuts import (render, redirect, reverse, HttpResponse)from rbac.utils import authcode# 用户登录视图类class Login(views.View):def get(self, request):# get请求返回登录页面return render(request, "login.html")def post(self, request):data = request.POST# 获取用户登录信息authcode = data.get("authcode")username = data.get("username")password = data.get("password")# 验证码不正确if request.session.get("authcode").upper() != authcode.upper():return JsonResponse({"status": "1"})else:# 使用django的auth模块进行用户名密码验证user = auth.authenticate(username=username, password=password)if user:# 将用户名存入session中request.session["user"] = usernameauth.login(request, user) # 将用户信息添加到session中return JsonResponse({"status": "2"})else:return JsonResponse({"status": "3"})# 验证码视图类class GetAuthImg(views.View):"""获取验证码视图类"""def get(self, request):data = authcode.get_authcode_img(request)print("验证码:",request.session.get("authcode"))return HttpResponse(data)

模板文件

系统的登录功能是通过ajax实现异步请求,后端验证数据,这种方式可以提高用户体验。

其次,登录页面使用的是adminLTE模板中的login页面,对页面进行自己的修改,login页面在adminLTE-master/pages/examples/login.html自取。

登录html页面,放在rbac应用下新建templates文件夹下。

{% load static %}<!DOCTYPE html><html><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>AliCRM | 登录</title><!-- Tell the browser to be responsive to screen width --><meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"><!-- Bootstrap 3.3.7 --><link rel="stylesheet" href="{% static 'adminlte/bower_components/bootstrap/dist/css/bootstrap.min.css' %}"><!-- Font Awesome --><link rel="stylesheet" href="{% static 'adminlte/bower_components/font-awesome/css/font-awesome.min.css' %}"><!-- Ionicons --><link rel="stylesheet" href="{% static 'adminlte/bower_components/Ionicons/css/ionicons.min.css' %}"><!-- Theme style --><link rel="stylesheet" href="{% static 'adminlte/dist/css/AdminLTE.min.css' %}"><!-- iCheck --><link rel="stylesheet" href="{% static 'adminlte/plugins/iCheck/square/blue.css' %}"></head><body class="hold-transition login-page"><div class="login-box"><div class="login-logo"><a href=""><b>Ali</b>CRM</a></div><!-- /.login-logo --><div class="login-box-body"><p class="login-box-msg">请登录</p><form action="" method="post">{% csrf_token %}<div class="form-group has-feedback"><input type="text" class="form-control" placeholder="username" name="username"><span class="glyphicon glyphicon-user form-control-feedback"></span><span class="username-error" style="color:#b14442"></span></div><div class="form-group has-feedback"><input type="password" class="form-control" placeholder="Password" name="password"><span class="glyphicon glyphicon-lock form-control-feedback"></span><span class="password-error" style="color:#b14442"></span></div><div class="row"><div class="col-sm-7"><div class="form-group has-feedback"><input type="text" class="form-control" placeholder="验证码" name="authcode"><span class="glyphicon glyphicon-barcode form-control-feedback"></span></div></div><div class="col-sm-4"><img id="authImg" src="{% url 'get_auth_img' %}" alt="验证码"></div></div><div class="row"><div class="col-xs-8"><div class="checkbox icheck"><label><input type="checkbox"> 是否记住帐号</label></div></div><!-- /.col --><div class="col-xs-4"><button type="button" id="loginBtn" class="btn btn-primary btn-block btn-flat">登录</button></div><!-- /.col --></div></form><div class="social-auth-links text-center"><p>- OR -</p><a href="#" class="btn btn-block btn-social btn-facebook btn-flat"><i class="fa fa-facebook"></i>使用微信登录</a></div><!-- /.social-auth-links --><a href="#">忘记密码</a><br><a href="{% url 'register' %}" class="text-center">注册一个新账号!</a></div><!-- /.login-box-body --></div><!-- /.login-box --><!-- jQuery 3 --><script src="{% static 'jquery/jquery-3.4.1.js' %}"></script><!-- Bootstrap 3.3.7 --><script src="{% static 'adminlte/bower_components/bootstrap/dist/js/bootstrap.min.js' %}"></script><!-- iCheck --><script src="{% static 'adminlte/plugins/iCheck/icheck.min.js' %}"></script><script>$(function () {$('input').iCheck({checkboxClass: 'icheckbox_square-blue',radioClass: 'iradio_square-blue',increaseArea: '20%' /* optional */});});// 登录ajax请求$("#loginBtn").on("click", function () {var username = $("input[name=username]").val();var password = $("input[name=password]").val();var authcode = $("input[name=authcode]").val();var csrf_token = $("input[name=csrfmiddlewaretoken]").val();if (!username) {$(".username-error").text("帐号不能为空!")}if (!password) {$(".password-error").text("密码不能为空!")}if (!authcode) {$(".authcode-error").text("请输入验证码")}$.ajax({url: "{% url 'login' %}",type: 'post',data: {username: username,password: password,authcode: authcode,csrfmiddlewaretoken: csrf_token,},success: function (res) {if (res.status === "1") {$(".authcode-error").text("验证码错误!")}if (res.status === "2") {var href = location.search.slice(6); //使用了auth的装饰器,会记录未登录用户想要访问的登录页面,登录成功后,会自动跳转过去if (href) {location.href = href //登录成功,有目标地址} else {location.href = "{% url 'index' %}" // 登录成功没有目标地址,跳转主页}}if (res.status === "3") {// 帐号密码错误$(".username-error").text("账号或密码错误!")}}})});// 验证码刷新$("#authImg").on("click", function () {$("#authImg")[0].src += "?" // 点击事件刷新验证码图片})</script></body></html>

注意:

该页面中的register和主页index还没有实现,所以路径反向解析会报错,可以先删除,以后在配置。

三、注册功能的实现

注册用户url配置

# 用户注册urlurl(r'^register/', account.Register.as_view(), name="register"),

注册视图类

注册视图涉及到前端提取数据到后端,并需要保存在数据库,所以数据需要校验合法性,数据的合法性校验有两种方式。

在前端通过js中的re正则方式去校验在后端校验数据的合法性,通过form组件

由于我们的前端水平啊,不堪一说,对我们来说也相对复杂,所以我们这里通过后端来校验数据的合法性,合法性校验也可以自己获取数据区较验,但是使用form组件来完成这个事情,更加高效,快速,准确。

既然要使用form那就需要先写一个form组件,这里关于rbac的form我们放在rbac/forms/formAuth.py文件中。

from django import formsfrom django.core.validators import RegexValidatorfrom django.core.exceptions import ValidationError# 注册form认证class RegForm(forms.Form):"""定义注册帐号的form组件"""username = forms.CharField(label = "用户名",max_length=18,error_messages={"required":"内容不能为空","invalid":"格式错误","max_length":"用户名最长不超过18位"},widget=forms.TextInput(attrs={"class":"forms-control"}))password = forms.CharField(min_length=6,error_messages={"required": "内容不能为空","invalid": "格式错误","min_length": "密码不能少于6位"})r_password = forms.CharField(min_length=6,error_messages={"required": "内容不能为空","invalid": "格式错误","min_length": "密码不能少于6位"})email = forms.CharField(label="邮箱",error_messages={"required": "内容不能为空","invalid": "格式错误",},validators=[RegexValidator(r"^\w+@\w+\.com$", "邮箱格式不正确")])phone = forms.CharField(label="电话",error_messages={"required": "内容不能为空","invalid": "格式错误",},validators=[RegexValidator(r"^[0-9]{4,11}$","请输入正确的号码")])# 定义局部钩子def clean_password(self):# 校验密码的合法性,不能为纯数据password = self.cleaned_data.get("password")if password.isdecimal():raise ValidationError("密码不能为纯数字!")return passworddef clean_r_password(self):# 校验密码的合法性,不能为纯数据r_password = self.cleaned_data.get("r_password")if r_password.isdecimal():raise ValidationError("密码不能为纯数字!")return r_password# 定义全局钩子def clean(self):# 校验两次密码输入是否一致if self.cleaned_data.get("password") != self.cleaned_data.get("r_password"):self.add_error("r_password","两次密码输入不一致!")else:return self.cleaned_data# 重写init方法,来批量设置标签的样式def __init__(self,*args,**kwargs):super().__init__(*args,**kwargs)for field in self.fields:self.fields[field].widget.attrs.update({"class":"forms-control"})

注册视图函数

from rbac.forms import formAuth# 注册视图类class Register(views.View):def get(self, request):# 注册页面的生成我们并没有用form,因为我们使用的别人的模板样式return render(request, "register.html")def post(self, request):# post请求提交注册数据data = request.POSTform_obj = formAuth.RegForm(data) # 数据交给form实例化if form_obj.is_valid(): # 验证提交数据的合法性valid_data = form_obj.cleaned_datausername = valid_data.get("username")# 判断帐号是否已存在if models.UserInfo.objects.filter(username=username):# 如果存在,给form中的username字段添加一个错误提示。form_obj.add_error("username", "帐号已存在")return render(request, "register.html", {"form_obj": form_obj})else:# 帐号可用,去掉多余密码,在数据库创建记录del valid_data["r_password"]models.UserInfo.objects.create_user(**valid_data) # 创建普通用户return redirect("login")else:# 数据验证不通过,返回页面和错误提示,保留数据return render(request, "register.html", {"form_obj": form_obj})

注册html页面

{% load static %}<!DOCTYPE html><html><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>AdminLTE 2 | Registration Page</title><!-- Tell the browser to be responsive to screen width --><meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"><!-- Bootstrap 3.3.7 --><link rel="stylesheet" href="{% static 'adminlte/bower_components/bootstrap/dist/css/bootstrap.min.css' %}"><!-- Font Awesome --><link rel="stylesheet" href="{% static 'adminlte/bower_components/font-awesome/css/font-awesome.min.css' %}"><!-- Ionicons --><link rel="stylesheet" href="{% static 'adminlte/bower_components/Ionicons/css/ionicons.min.css' %}"><!-- Theme style --><link rel="stylesheet" href="{% static 'adminlte/dist/css/AdminLTE.min.css' %}"><!-- iCheck --><link rel="stylesheet" href="{% static 'adminlte/plugins/iCheck/square/blue.css' %}"></head><body class="hold-transition"><div class="register-box"><div class="register-logo"><a href=""><b>Ali</b><span class="small">CRM</span></a></div><div class="register-box-body" style="border: #bbb 1px solid;border-radius: 2px"><p class="login-box-msg">注册一个帐号</p><form action=".{% url 'register' %}" method="post" novalidate>{% csrf_token %}<div class="form-group has-feedback"><input type="text" class="form-control" placeholder="用户名" name="username"><span class="glyphicon glyphicon-user form-control-feedback"></span><span class="has-error">{{ form_obj.username.errors.0 }}</span></div><div class="form-group has-feedback"><input type="password" class="form-control" placeholder="密码" name="password"><span class="glyphicon glyphicon-lock form-control-feedback"></span><span class="has-error">{{ form_obj.password.errors.0 }}</span></div><div class="form-group has-feedback"><input type="password" class="form-control" placeholder="确认密码" name="r_password"><span class="glyphicon glyphicon-log-in form-control-feedback"></span><span class="has-error">{{ form_obj.r_password.errors.0 }}</span></div><div class="form-group has-feedback"><input type="email" class="form-control" placeholder="邮箱" name="email"><span class="glyphicon glyphicon-envelope form-control-feedback"></span><span class="has-error">{{ form_obj.email.errors.0 }}</span></div><div class="form-group has-feedback"><input type="text" class="form-control" placeholder="电话" name="phone"><span class="glyphicon glyphicon-phone form-control-feedback"></span></div><div class="row"><div class="col-xs-8"><div class="checkbox icheck"><label><input type="checkbox">我同意该<a href="#">条款</a></label></div></div><!-- /.col --><div class="col-xs-4"><button type="submit" class="btn btn-primary btn-block btn-flat">注册</button></div><!-- /.col --></div></form><div class="social-auth-links text-center"><p>- OR -</p><a href="#" class="btn btn-block btn-social btn-success btn-flat"><span class="glyphicon glyphicon-qrcode"></span><i class=""></i>微信登录</a></div><a href="{% url 'login' %}" class="text-center">已经拥有账号</a></div><!-- /.form-box --></div><!-- /.register-box --><!-- jQuery 3 --><script src="{% static 'adminlte/bower_components/jquery/dist/jquery.min.js' %}"></script><!-- Bootstrap 3.3.7 --><script src="{% static 'adminlte/bower_components/bootstrap/dist/js/bootstrap.min.js' %}"></script><!-- iCheck --><script src="{% static 'adminlte/plugins/iCheck/icheck.min.js' %}"></script><script>$(function () {$('input').iCheck({checkboxClass: 'icheckbox_square-blue',radioClass: 'iradio_square-blue',increaseArea: '20%' /* optional */});});</script></body></html>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。