登录(验证码)、注册功能具体代码

# urls.py

from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls), path("login/",views.login), #登录
path("get_valid_img/",views.get_valid_img), #生成验证码
path("reg/",views.reg) #注册 ]

# views.py

# Create your views here.
import random
import re
from io import BytesIO from PIL import Image, ImageDraw, ImageFont
from django import forms
from django.contrib import auth
from django.core.exceptions import ValidationError
from django.forms import widgets
from django.http import JsonResponse
from django.shortcuts import render, HttpResponse from app01.models import UserInfo ###################### 创建UserForm用户校验,输入的内容是否合法##############
class UserForm(forms.Form):
user = forms.CharField(min_length=5, label='用户名')
pwd = forms.CharField(min_length=5, widget=widgets.PasswordInput(), label="密码")
r_pwd = forms.CharField(min_length=5, widget=widgets.PasswordInput(), label="确认密码")
email = forms.EmailField(min_length=5, label="邮箱") # 为每一个字段 input 添加类名 form-control
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for filed in self.fields.values():
filed.widget.attrs.update({'class': 'form-control'}) def clean_user(self):
val = self.cleaned_data.get('user')
user = UserInfo.objects.filter(username=val).first()
if user:
raise ValidationError('用户名已存在!')
else:
return val def clean_pwd(self):
val = (self.cleaned_data.get('pwd'))
if val.isdigit():
raise ValidationError('密码不能为纯数字!')
else:
return val def clean_email(self):
val = self.cleaned_data.get('email')
if re.search("\w+@163.com$", val):
return val
else:
raise ValidationError('邮箱必须是163格式邮箱!') def clean(self): # 全局校验
pwd = self.cleaned_data.get('pwd')
r_pwd = self.cleaned_data.get('r_pwd')
if pwd and r_pwd and pwd != r_pwd:
# raise ValidationError("两次密码不一致!") # 也可以采用以下方法,这样在渲染的时候可以不用特殊处理,全局的错误会在r_pwd中,不再是__all__
self.add_error("r_pwd", ValidationError('两次密码不一致!'))
else:
return self.cleaned_data ####################### 登录 ######################
def login(request):
if request.method == "GET":
return render(request, "login.html") else:
user = request.POST.get("user")
pwd = request.POST.get("pwd")
validcode = request.POST.get("validcode") res = {"user": None, "error_msg": ""}
if validcode.upper() == request.session.get("keep_str").upper():
user_obj = auth.authenticate(username=user, password=pwd)
if user_obj:
res["user"] = user
else:
res["error_msg"] = "用户名或密码错误!"
else:
res["error_msg"] = "验证码错误" return JsonResponse(res) ####################### 生成验证码 ################################
def get_valid_img(request):
def get_random_color():
return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) # 生成图片
img = Image.new("RGB", (250, 35), get_random_color())
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("static/font/kumo.ttf", 32) keep_str = '' # 用于存储验证码,用户后台校验 # 为图片添加随机文本text
for i in range(6):
rand_num = str(random.randint(0, 9))
rand_lowalp = chr(random.randint(97, 122))
rand_upealp = chr(random.randint(65, 90)) random_char = random.choice([rand_num, rand_lowalp, rand_upealp]) draw.text((i * 30 + 50, 0), random_char, get_random_color(), font=font)
keep_str += random_char # --------加噪点和噪线------
width = 250
height = 35
for i in range(3):
x1 = random.randint(0, width)
x2 = random.randint(0, width)
y1 = random.randint(0, height)
y2 = random.randint(0, height)
draw.line((x1, y1, x2, y2), fill=get_random_color()) for i in range(2):
draw.point([random.randint(0, width), random.randint(0, height)], fill=get_random_color())
x = random.randint(0, width)
y = random.randint(0, height)
draw.arc((x, y, x + 4, y + 4), 0, 90, fill=get_random_color()) # 将生成的图片进行读写
f = BytesIO() # 写,在内存中创建文件句柄
img.save(f, "png") # 将img保存在句柄中 data = f.getvalue() # 读取图片字节,返回给img响应 # 生成的随机字符串,加到sesstion中,传给用户,在用户登录时候进行校验,不能将随机字符串作为全局变量
request.session["keep_str"] = keep_str # 将图片字节 直接响应回图片
return HttpResponse(data) ########################## 注册 ##########################
def reg(request):
if request.method == "GET":
userform = UserForm()
return render(request, "reg.html", locals())
else:
form = UserForm(request.POST) res = {"user": None, "err_msg": ""} if form.is_valid():
user = form.cleaned_data.get('user')
pwd = form.cleaned_data.get('pwd')
email = form.cleaned_data.get('email') UserInfo.objects.create_user(username=user, password=pwd, email=email) res['user'] = user
else:
res['err_msg'] = form.errors return JsonResponse(res)

# login.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Login</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
<style type="text/css">
body{
background:url(/static/img/小桥.jpg);
background-size:100%;
background-attachment: fixed;
} </style>
</head>
<body>
<h1 class="text-primary" style="text-align: center;line-height:150px">登录页面</h1> <div class="container">
<div class="row"> <div class="col-lg-4 col-md-offset-4">
{# <form action="" method="post">#}
{% csrf_token %}
<div class="form-group">
<label for="">用户名</label>
<input type="text" class="form-control " placeholder="用户名" id="user">
</div>
<div class="form-group">
<label for="">密码</label>
<input type="password" class="form-control" placeholder="密码" id="pwd">
</div>
<div class="form-group">
<label for="">验证码</label>
<div class="row">
<div class="col-md-6">
<input type="text" class="form-control" placeholder="验证码" id="validcode">
</div>
<div class="col-md-6">
<img width="165" height="35" src="/get_valid_img/" alt="" id="img">
</div>
</div>
</div>
<input type="button" class="btn btn-primary btn-block pull-right login_btn" value="登录">
<p><a href="/reg/" style="text-align: center;display: block">还没有账号,去注册?</a></p>
<span class="error"></span>
{# </form>#}
</div>
</div>
</div> <script src="/static/js/jquery.js"></script>
<script type = "text/javascript">
window.onload = function() {
var config = {
vx : 4,
vy : 4,
height : 2,
width : 2,
count : 100,
color : "121, 162, 185",
stroke : "100, 200, 180",
dist : 6000,
e_dist : 20000,
max_conn : 10
}
CanvasParticle(config);
}
</script>
<script type = "text/javascript" src="/static/js/canvas-particle.js"></script>
<script>
//登录数据
$(".login_btn").click(function () {
console.log(6666)
$.ajax({
url:"/login/",
type:"post",
data:{
user:$("#user").val(),
pwd:$("#pwd").val(),
validcode:$("#validcode").val(),
csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val()
},
success:function (response) {
{#console.log(response.user);#}
if(response.user){
//登陆成功
console.log(111111);
location.href="/homepage/";
{#alert(111111)#}
}
else{
//登陆失败
$(".error").html(response.err_msg).css("color","reg")
}
}
})
})
//验证码刷新
$("#img").click(function () {
this.src+="?"
}) </script> </body>
</html>

# register.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Register</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
<style type="text/css">
body{
background:url(/static/img/山水.jpg);
background-size:100%;
background-attachment: fixed;
} </style>
</head>
<body>
<h1 class="text-primary" style="text-align: center;line-height:150px">注册页面</h1> <div class="container">
<div class="row">
<div class="col-lg-4 col-md-offset-4">
{% csrf_token %}
<div class="form-group">
<label for="">用户名</label>
<input type="text" class="form-control" placeholder="用户名" id="user">
<span class="error pull-right"></span>
</div>
<div class="form-group">
<label for="">密码</label>
<input type="password" class="form-control" placeholder="密码" id="pwd">
<span class="error pull-right"></span>
</div>
<div class="form-group">
<label for="">确认密码</label>
<input type="password" class="form-control" placeholder="确认密码" id="r_pwd">
<span class="error pull-right"></span>
</div>
<div class="form-group">
<label for="">邮箱</label>
<input type="email" class="form-control" placeholder="邮箱" id="email">
<span class="error pull-right"></span>
</div>
<input type="button" class="btn btn-primary btn-block pull-right" id="reg_btn" value="注册">
<p><a href="/login/" style="text-decoration:none; text-align: center;display: block">已注册,请点击登录</a></p>
<span class="error pull-right"></span>
</div>
</div>
</div> <script src="/static/js/jquery.js"></script>
<script type = "text/javascript">
window.onload = function() {
var config = {
vx : 4,
vy : 4,
height : 2,
width : 2,
count : 100,
color : "121, 162, 185",
stroke : "100, 200, 180",
dist : 6000,
e_dist : 20000,
max_conn : 10
}
CanvasParticle(config);
}
</script>
<script type = "text/javascript" src="/static/js/canvas-particle.js"></script>
<script>
//注册数据
$("#reg_btn").click(function () {
console.log(1111);
$.ajax({
url:"/reg/",
type:"post",
data:{
csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val(),
user:$("#user").val(),
pwd: $("#pwd").val(),
r_pwd:$("#r_pwd").val(),
email:$("#email").val(),
},
success:function (response) {
console.log(response);
if (response.user){
//注册成功
location.href="/login/"
}
else{
//清除错误
$(".error").html("");
$(".form-group").removeClass("has-error"); //展示错误
$.each(response.err_msg,function (i,j) {
$("#"+i).next().html(j[0]).css("color","red").parent().addClass("has-error") })
} }
})
}) </script>
</body>
</html>

# models.py

from django.db import models

# Create your models here.

from django.contrib.auth.models import AbstractUser

class UserInfo(AbstractUser):
tel = models.CharField(max_length=32)

知识点补充总结

1、用户认证组中 用户表需要扩展时

用户认证组件中验证的信息是存储信息是依赖于 auth_user 表中的,但是该表的中字段是有限的,比如注册的时候想输入手机号等,因此,想要扩展user表,我们就需要创建一个新的userinfo表来代替auth_user 表。

需要在 setting 中设置(项目为app01,models表为UserInfo):

AUTH_USER_MODEL="app01.UserInfo"

models中创建的表需要继承 AbstractUser,其实 auth_user  也是继承了该类,因此,新创建的表就有了原来表中的字段还可以添加新字段

from django.db import models

# Create your models here.

from django.contrib.auth.models import AbstractUser

class UserInfo(AbstractUser):   #继承
tel = models.CharField(max_length=32)

数据库的迁移:

python manage.py makemigrations
python manage.py migrate 

#在数据库auth_user或其替代表中,创建数据(通过终端)创建超级用户 createsuperuser

2、img标签中发送请求(有个特殊功能)

img标签有一个特殊的功能,去发送请求,可以实现图片的局部刷新,典型的是验证码图片的刷新,

加问号,等于多次访问该地址,而验证码中该地址每次访问都会获取不同的随机验证码图片,因此可以实现局部的刷新验证码

{# 验证码的刷新 #}
$("#valid_img_btn").click(function () {
this.src += "?"
});

3、验证码的校验

登录验证的时候,如何校验验证码?

后台中在生成验证码的方法 获取的随机字符串 为 keep_str , 但是在login方法中,接收的数据如何跟 其他方法中的 keep_str 进行比较?

有人说,将keep_str 存成全局变量 gloabl, 这样是可以满足比较,但是不同的用户要有不同的验证码,这样的话,只有最后用户刷新页面生成的验证码才是真的,有用户1在登录界面,还没有来得及输入,其他用户2也进入登录界面,那么验证码发生了变化,用户1 根据页面展示的验证码即便输入正确也会登录失败。

因此,我们要将各用户的验证码存到各自的 session 中: 

# 设置session
request.session[keep_str":keep_str] # 获取session
request.session.get("keep_str")

session  或者  用户认证组件,都会在 django-session表中生成记录,

一个浏览器访问会有一条记录,两个浏览器访问会有2条记录,里面的记录个数与访问的浏览器的个数一致。

session 不仅可以用于登录,校验验证码,以后还会有很多的用处。

4、JsonResponse

视图函数中,引入JsonResponse,用次返回数据,不必再转换成就送数据,而前台接收到数据,也不需要反序列化,这些步骤在内部已经封装好了。

from django.http import JsonResponse

return JsonResponse({"user":user,"error":""})

5、字母与ASCII的对应

a ~ z      97 ~ 122

A ~ Z     65 ~ 90

6、Form组件中  errors中的 __all__

在全局的钩子中,其错误直接 raise ValidationError("用户密码不一致"),会存储在errors的__all__中

form = UserForm(request.POST)

if form.is_valid():
  form.cleaned_data else:
  form.errors #是个字典
  form.errors.get("__all__") #全局钩子中的具体错误

但是全局钩子如果是以下,全局的错误会存储在r_pwd中:

 

Django---登录(含随机生成图片验证码)、注册示例讲解的更多相关文章

  1. Django登录(含随机生成图片验证码)注册实例

    登录,生成随机图片验证码 一.登录 - 随机生成图片验证码 1.随机生成验证码 Python随机生成图片验证码,需要使用PIL模块,安装方式如下: pip3 install pillow 1)创建图片 ...

  2. python 全栈开发,Day85(Git补充,随机生成图片验证码)

    昨日内容回顾 第一部分:django相关 1.django请求生命周期 1. 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端 请求头和请求体中会包含浏览器的动作(action),这 ...

  3. servletResponse 随机生成图片验证码

    /***********************************servlet页面************************************/ package response; ...

  4. Java代码随机生成图片验证码

    package com.rchm.util.images; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2 ...

  5. python 随机生成图片验证码背景RGB-浅色或者深色

    import random def random_color(is_light = True): return (random.randint(0 ,127) + int(is_light) * 12 ...

  6. django项目登录中使用图片验证码

    应用下创建untils文件夹放置封装图片验证码的函数 创建validCode.py文件定义验证码规则 import random def get_random_color(): return (ran ...

  7. python - django (实现电子邮箱的账户注册和验证码功能)

    使用 Django 来做一个电子邮箱注册 并 发送验证码的功能 (此处以 163 邮箱为例) 一. 登陆 163 邮箱账号,  然后进行下列操作 二. settings 配置文件 # 发送邮箱验证码 ...

  8. Django中生成随机验证码(pillow模块的使用)

    Django中生成随机验证码 1.html中a标签的设置 <img src="/get_validcode_img/" alt=""> 2.view ...

  9. 使用Struts2搭建登录注册示例

    使用Struts2来搭建mvc网站框架还是比较容易的,Struts2提供了各项辅助功能,保证了web开发的快速方便.下面使用struts2来搭建一个登录注册示例. 0 项目结构截图 1 搭建Strut ...

随机推荐

  1. 使用 Python 发送短信?

    上回食行生鲜签到,我们说到怎么把签到结果发出来,于是就找到了 Twilio. Twilio 是一个位于加利福尼亚的云通信(PaaS)公司,致力于为开发者提供通讯模块的 API.由于 Twilio 为试 ...

  2. NOIP 2011 DAY 2

    第一题:计算系数 题目 给定一个多项式 (ax+by)k​​,请求出多项式展开后x​​ny​m​​ 项的系数. 输入 共一行,包含 5 个整数,分别为 a,b,k,n,m,每两个整数之间用一个空格隔开 ...

  3. Operating System-Thread(1)What and Why Thread &&进程和线程的对比

    开始线程(Thread)之旅,作为程序员,打交道更多的是线程,各种多线程程序,并行编程都是以线程为基础进行的.本文主要内容: What and Why Thread 进程和线程的对比 一.What a ...

  4. POJ2559:Largest Rectangle in a Histogram

    浅谈栈:https://www.cnblogs.com/AKMer/p/10278222.html 题目传送门:http://poj.org/problem?id=2559 贪心的想,最大的子矩阵顶部 ...

  5. java代码for循环+缓冲流类

    总结:这个结果竟然是对的.我错了. package com.da; //创建一个String对象的数组,然后执行读取文本,把文本每一行存入数组,它将读取到100行 //或直接到你按”stop“才停止, ...

  6. web攻击之五:上传漏洞

    [攻击] 在图片上传的时候,攻击者上传非图片,而是可远程执行的的脚本,这时候,入侵者就可以远程的执行脚本来对服务器进行攻击 [防御] 1.限制文件上传类型 2.使用第三方文件托管等

  7. Java父类构造器的讲解

    众所周知,对于Java中的所有类而言,它们有一个根父类,即java.lang.Object类. 对于Java中构造器执行的顺序而言,程序执行的顺序为,先执行父类的非静态代码块,然后执行父类的相应的构造 ...

  8. Asp.net mvc 网站之速度优化 -- 页面缓存

    网站速度优化的一般方法 由于网站最重要的用户体验就是速度,特别是对于电子商务网站而言. 一般网站速度优化会涉及到几个方面: 1. 数据库优化 — 查询字段简历索引,使用数据库连接池和持久化,现在还有种 ...

  9. 字符编码ASCII、Unicode、GB

    计算机的存储都是二进制的,那么我们平时看到的各种字符都需要通过按照一定的格式转换成为二进制才能在被计算机识别与处理.这个过程便成为编码.常见的编码方式有ASCII.Unicode.GB2312等. 1 ...

  10. redis持久化  发布消息与订阅

    vi /usr/local/redis/etc/redis.conf  快照方式:     save 900 1     save 300 10     save 60 10000 aof方式: ap ...