Python(18)——Django实战1之可重用注册登录系统(从面到点剖析)
文章目录
- 前言
- 0、项目开始前的思考
- 1、搭建项目环境(和上一篇文章一样)
- 1.1 创建Django项目
- 1.2 创建app
- 1.3 设置时区(中文显示)
- 1.4 数据库表生成
- 1.5 启动开发服务器
- 1.6 浏览器访问,检测是否成功?
- 1.7 git提交项目代码到本地仓库(阶段性提交,有助于恢复)
- 2、设计数据库模型
- 2.1 设计要点
- 2.2 数据库模型文件
- 2.3 设置数据库后端
- 2.4 注册app
- 2.5 生成迁移脚本并写入数据库
- 2.6 数据库模型后台管理
- 3、路由与视图函数框架搭建
- 3.1 路由设计
- 3.2 访问策略
- 3.3 路由配置
- 3.3.1 主路由配置文件
- 3.3.2 子路由配置文件(login子应用的)
- 3.4 视图函数的配置
- 3.5 模板template的配置
- 4、前端界面设计与优化
- 4.1 python开发人员的前端速成之路
- 4.2 完善登录的视图函数
- 4.3 git提交下本地仓库
- 5、session会话与登录的视图函数
- 5.1 登入
- 5.2 登出时,清空session信息
- 5.3 添加登出的超链接
- 5.4 git到本地仓库
- 6、上传到gitee
- 6.1 注册新账号并新建仓库
- 6.2 上传到gitee仓库准备工作
- 6.2.1 创建README.md文件(说明文档)
- 6.2.2 生成requirements.txt文件(所需的包)
- 6.3 绑定gitee仓库
- 6.4 上传
- 6.5 查看之前版本
- 6.6 命令行查看分支或增加切换分支
- 7、图片验证码
- 7.1 安装插件
- 7.2 上传gitee仓库
- 7.3 Django表单
- 7.3.1 创建表单模型
- 7.3.2 视图逻辑优化
- 7.3.3 Template页面优化
- 7.4 git提交下版本
- 8、 邮箱注册(重点)
- 8.1 获取授权码并开启SMTP
- 8.2 配置邮件信息
- 8.3 交互式环境中测试发送邮件是否成功?
- 8.4 注册表单
- 8.5 实现注册视图
- 8.6 Template模板的更改
- 8.7 注册添加密码加密功能
- 8.7.1 改动
- 8.7.2 上传git
- 8.8 邮箱注册确认(是否是真正的邮箱)
- 8.8.1 创建模型
- 8.8.2 修改 login/utils.py
- 8.8.3 修改视图 login/views.py
- 8.8.4 提交代码
前言
上一篇文章已经学了django的基本使用,这篇文章将以另一个实例再次讲解django,有相似地方,也有更进的地方。Django框架入门-项目创建与认识子应用
本篇文章的重点:
- 注册(邮箱注册,手机,微信,QQ)
- 登录
- 注销
0、项目开始前的思考
路由配置
urlpattern = [
path('/register/', views.register),
path('/login/', views.login),
path('/logout/', views.logout),
]
视图配置(重点)----
数据库模型Model:
class User:
id, name, password, email, create_time, update_time
last_time(最后一次登录的时间), gender, province
模板Template: register.html, login.html, index.html
…
1、搭建项目环境(和上一篇文章一样)
1.1 创建Django项目
1.2 创建app
在终端输入:
$ python manage.py startapp login
1.3 设置时区(中文显示)
# filename: loginRegister/settings.py
# LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = 'zh-hans' ## 中文
# TIME_ZONE = 'UTC'
TIME_ZONE = 'Asia/Shanghai' ## 地区为亚洲/上海
1.4 数据库表生成
在终端输入:
$ python manage.py migrate # 将迁移脚本的内容写入数据库并创建数据库表
$ python manage.py createsuperuser # 创建后台登录的超级用户
1.5 启动开发服务器
方法一: 命令启动
在终端输入:
$ python manage.py runserver 9999
方法二: 配置Django Server
1.6 浏览器访问,检测是否成功?
- 访问网址: http://127.0.0.1:9999/
- 访问网址: http://127.0.0.1:9999/admin/
1.7 git提交项目代码到本地仓库(阶段性提交,有助于恢复)
先安装插件.ignore, 并生成python上传git项目需要忽略内容的文件.gitignore
$ git init
$ git add * # 添加修改到暂存区
$ git commit -m "搭建项目开发环境" # 将暂存区的代码提交到本地git仓库
$ git log # 查看历史提交记录
2、设计数据库模型
2.1 设计要点
作为一个用户登录和注册项目,需要保存的都是各种用户的相关信息。很显然,我们至少需要一张用户
表User,在用户表里需要保存下面的信息:
用户名(name): 必填,最长不超过128个字符且唯一(unique)
密码(password): 必填,最长不超过256个字符
邮箱地址(email): 使用Django内置的邮箱类型且唯一
性别(gender): 性别, 使用choice,只能选择男或者女或者未知,默认为未知;
创建时间(create_time): 用户创建时间
- 注意点: auto_now_add=True时为添加时的时间,更新对象时不会有变动。
修改时间(modify_time):用户最后一次修改时间
- 注意点: auto_now=True无论是你添加还是修改对象,时间为你添加或者修改的时间。
最后一次登录时间(last_login_time): 最后一次登录时间
- 注意点:null=True的话,数据库中该字段是NULL,即允许空值
- 注意点:blank=False(默认)的话,字段没被赋值则会抛错;和数据验证(表单验证等)有
关.
2.2 数据库模型文件
# login/models.pyfrom django.db import models
# Create your models here.
# appname_siteuser
class SiteUser(models.Model):"""用户的数据库模型,注册/登录需要"""gender_choice = ((0, "未知"),(1, "男"),(2, "女"),)name = models.CharField(max_length=128, unique=True, verbose_name="用户名")password = models.CharField(max_length=256, verbose_name="密码")email = models.EmailField(unique=True, verbose_name="电子邮箱")gender = models.IntegerField(choices=gender_choice, default=0,
verbose_name="性别")# auto_now_add=True时为添加时的时间,更新对象时不会有变动。# auto_now=True无论是你添加还是修改对象,时间为你添加或者修改的时间。create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")modify_time = models.DateTimeField(auto_now=True, verbose_name="最后一次修改时间")# null针对数据库层面的, blank针对表单的last_login_time = models.DateTimeField(null=True, blank=True,verbose_name="最后一次登录时间")def __str__(self):return self.nameclass Meta:verbose_name = "网站用户管理"verbose_name_plural = verbose_name
2.3 设置数据库后端
Django支持MySQL, Sqlite, oracle等数据库, 此处选择默认的sqlite,不做修改。
2.4 注册app
# loginRegister/settings.pyINSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','login', # 修改的内容
]
2.5 生成迁移脚本并写入数据库
在终端输入:
$ python manage.py makemigrations #生成数据库迁移脚本
$ python manage.py migrate # 将迁移脚本的内容写入数据库并创建数据库表
$ python manage.py createsuperuser # 创建后台登录的超级用户
2.6 数据库模型后台管理
# login/admin.pyfrom django.contrib import admin
from login.models import SiteUser
# Register your models here.
# 后台管理设置的信息
class SiteUserAdmin(admin.ModelAdmin):list_display = ['name', 'gender', 'email']list_display_links = ['name']list_filter = ['gender', 'create_time']list_per_page = 10
admin.site.register(SiteUser, SiteUserAdmin)
浏览器访问,检测是否成功?
访问网址: http://127.0.0.1:9999/admin/
3、路由与视图函数框架搭建
3.1 路由设计
3.2 访问策略
- 未登录人员,不论是访问index还是login和logout,全部跳转到login界面
- 已登录人员,访问login会自动跳转到index页面
- 已登录人员,不允许直接访问register页面,需先logout
- 登出后,自动跳转到login界面
3.3 路由配置
3.3.1 主路由配置文件
# loginRegister/urls.pyfrom django.contrib import admin
from django.urls import path, include
urlpatterns = [path('admin/', admin.site.urls),path('', include('login.urls')) # 添加的行, 如果没有前缀,访问子路由配置文件
]
3.3.2 子路由配置文件(login子应用的)
# login/urls.py(新建的文件)from django.urls import path, include
from login import views
urlpatterns = [path('index/', views.index, name='index'),path('login/', views.login, name='login'),path('register/', views.register, name='register'),path('logout/', views.logout, name='logout'),
]
3.4 视图函数的配置
# login/views.pyfrom django.shortcuts import render, redirect
# Create your views here.def index(request):passreturn render(request, 'login/index.html')
def login(request):passreturn render(request, 'login/login.html')
def register(request):passreturn render(request, 'login/register.html')
def logout(request):pass# redirect: 重定向(跳转)return redirect('/login/')
3.5 模板template的配置
- templates/login/index.html(新建)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>首页</title>
</head>
<body>
<h1>这是首页的模拟界面</h1>
</body>
</html>
- templates/login/login.html(新建)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>用户登录</title>
</head>
<body>
<h1>用户登录</h1>
<form>用户名: <input type="text" placeholder="username"><br/>密码: <input type="password" placeholder="password"><br/><input type="submit" value="登录">
</form>
</body>
</html>
- templates/login/register.html(新建)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>注册界面</title>
</head>
<body>
<h1>用户注册</h1>
<form>用户名: <input type="text" placeholder="username"><br/>电子邮箱: <input type="email" placeholder="email"><br/>密码: <input type="password" placeholder="password"><br/>确认密码: <input type="password" placeholder="password"><br/><input type="submit" value="注册">
</form>
</body>
</html>
浏览器访问,检测是否成功?
访问网址: http://127.0.0.1:9999/index/
访问网址: http://127.0.0.1:9999/login/
访问网址: http://127.0.0.1:9999/register/
4、前端界面设计与优化
4.1 python开发人员的前端速成之路
在颜值即正义的年代,但没有CSS和JS,样子真的令人无法接受。
然而,大多数使用Django的人都不具备多高的前端水平,通常也没有专业的前端工程师配合,自己写的
CSS和JS却又往往惨不忍睹。怎么办?没关系,我们有现成的开源前端CSS框架!Bootstrap4就是最好
的CSS框架之一!戳一下了解更多
Bootstrap核心汇总:
- Bootstrap入门模板
- Bootstrap栅栏系统
- Bootstrap表单组件
- Bootstrap警告框
# index.html<!doctype html>
<html lang="zh-CN"><head><!-- 必须的 meta 标签 --><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><!-- Bootstrap 的 CSS 文件 --><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous"><title>首页</title></head><body><h1>这是首页的模拟界面</h1><!-- JavaScript 文件是可选的。从以下两种建议中选择一个即可! --><!-- 选项 1:jQuery 和 Bootstrap 集成包(集成了 Popper) --><script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script><script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-LCPyFKQyML7mqtS+4XytolfqyqSlcbB3bvDuH9vX2sdQMxRonb/M3b9EmhCNNNrV" crossorigin="anonymous"></script><!-- 选项 2:Popper 和 Bootstrap 的 JS 插件各自独立 --><!--<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script><script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script><script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.min.js" integrity="sha384-gRC4eoaRyQ8xv2X6Mnf+eOIrtON3wId3dAkwO0HQX26OrFBoLpjX/XWOJacSiZhL" crossorigin="anonymous"></script>--></body>
</html># login.html<!doctype html>
<html lang="zh-CN">
<head><!-- 必须的 meta 标签 --><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><!-- Bootstrap 的 CSS 文件 --><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css"integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous"><title>用户登录</title>
</head>
<body>
<div class="container"><div class="row"><div class="col-sm"></div><div class="col-sm"><h3 style="text-align: center">用户登录</h3><div class="alert alert-warning" role="alert"><strong>登录失败!</strong> 用户密码错误!</div><form><div class="form-group"><label>用户名</label><input type="text" class="form-control"></div><div class="form-group"><label>Password</label><input type="password" class="form-control"><small class="form-text text-muted">密码必须是字母、数字或者特殊符号组成.</small></div><a href="/register/" class="text-success"><ins>新用户注册</ins></a><button type="submit" class="btn btn-primary float-right">登录</button></form></div><div class="col-sm"></div></div>
</div>
<!-- JavaScript 文件是可选的。从以下两种建议中选择一个即可! --><!-- 选项 1:jQuery 和 Bootstrap 集成包(集成了 Popper) -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js"integrity="sha384-LCPyFKQyML7mqtS+4XytolfqyqSlcbB3bvDuH9vX2sdQMxRonb/M3b9EmhCNNNrV"crossorigin="anonymous"></script><!-- 选项 2:Popper 和 Bootstrap 的 JS 插件各自独立 -->
<!--
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.min.js" integrity="sha384-gRC4eoaRyQ8xv2X6Mnf+eOIrtON3wId3dAkwO0HQX26OrFBoLpjX/XWOJacSiZhL" crossorigin="anonymous"></script>
-->
</body>
</html># register.html<!doctype html>
<html lang="zh-CN">
<head><!-- 必须的 meta 标签 --><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><!-- Bootstrap 的 CSS 文件 --><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css"integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous"><title>注册界面</title>
</head>
<body>
<div class="container"><div class="row"><div class="col-sm"></div><div class="col-sm"><h3 style="text-align: center">用户注册</h3><form><div class="form-group"><label>用户名</label><input type="text" class="form-control"></div><div class="form-group"><label>电子邮箱</label><input type="email" class="form-control"></div><div class="form-group"><label>密码</label><input type="password" class="form-control"><small class="form-text text-muted">密码必须是字母、数字或者特殊符号组成.</small></div><div class="form-group"><label>确认密码</label><input type="password" class="form-control"><small class="form-text text-muted">密码必须是字母、数字或者特殊符号组成.</small></div><a href="/login/" class="text-success"><ins>用户登录</ins></a><button type="submit" class="btn btn-primary float-right">注册</button></form></div><div class="col-sm"></div></div>
</div>
<!-- JavaScript 文件是可选的。从以下两种建议中选择一个即可! --><!-- 选项 1:jQuery 和 Bootstrap 集成包(集成了 Popper) -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js"integrity="sha384-LCPyFKQyML7mqtS+4XytolfqyqSlcbB3bvDuH9vX2sdQMxRonb/M3b9EmhCNNNrV"crossorigin="anonymous"></script><!-- 选项 2:Popper 和 Bootstrap 的 JS 插件各自独立 -->
<!--
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.min.js" integrity="sha384-gRC4eoaRyQ8xv2X6Mnf+eOIrtON3wId3dAkwO0HQX26OrFBoLpjX/XWOJacSiZhL" crossorigin="anonymous"></script>
-->
</body>
</html>
测试:
4.2 完善登录的视图函数
错误原因是CSRF验证失败,请求被中断。CSRF(Cross-site request forgery)跨站请求伪造,是一种常见的网络攻击手段,具体原理和技术内容请自行百科。Django自带对许多常见攻击手段的防御机制,CSRF就是其中一种,还有XSS、SQL注入等。
解决这个问题的办法其实在Django的Debug错误页面已经给出了,我们需要在前端页面的form表单内添加一个{% csrf_token %}标签
html和视图函数交互的完善
- 修改1. 有message信息则显示, 没有就不显示。
- 修改2: 提交登录信息时, 以post方法提交给/login/对应的是视图函数处理。
- 修改3: Django提供了csrf防攻击的机制, 添加该信息则可顺利访问登陆界面
- 修改4:name="username"指定表单内容存储的key值名称, eg: {“username”:“你填的用户
名”,“password”:“你填的密码” }
//此文件是在原来基础上进行修改的<title>用户登录</title>
</head>
<body>
<div class="container"><div class="row"><div class="col-sm"></div><div class="col-sm"><h3 style="text-align: center">用户登录</h3># 修改1. 有message信息则显示, 没有就不显示。{% if message %}<div class="alert alert-warning" role="alert"><strong>登录失败!</strong> {{ message }}</div>{% endif %}# 修改2: 提交登录信息时, 以post方法提交给/login/对应的是视图函数处理。<form action="/login/" method="post"># 修改3: Django提供了csrf防攻击的机制, 添加该信息则可顺利访问登陆界面{% csrf_token %}<div class="form-group"><label>用户名</label># 修改4:name="username"指定表单内容存储的key值名称, eg:
{"username":"你填的用户名"}<input type="text" class="form-control" name="username"></div><div class="form-group"><label>Password</label><input type="password" class="form-control" name="password"><small class="form-text text-muted">密码必须是字母、数字或者特殊符号组成.</small></div><a href="/register/" class="text-success"><ins>新用户注册</ins></a><button type="submit" class="btn btn-primary float-right">登录</button></form></div><div class="col-sm"></div></div>
</div>
视图函数的完善(login部分)
def login(request):if request.method == 'POST':username = request.POST.get('username').strip()password = request.POST.get('password').strip()print(username, password)print(request.POST)if username and password:user = SiteUser.objects.filter(name=username,password=password).first()if user:return redirect('/index/')else:message = "用户名或者密码错误"return render(request, 'login/login.html',{'message': message})else:message = "非法的数据信息"return render(request, 'login/login.html', {'message': message})return render(request, 'login/login.html')
测试:
先添加用户
使用错误用户登录
使用正确用户登录:
4.3 git提交下本地仓库
git add *
git commit -m "完善登录视图函数"
5、session会话与登录的视图函数
- 登录成功, 存储登录的用户信息到session中
5.1 登入
# login/views.pydef login(request):if request.method == 'POST':username = request.POST.get('username').strip()password = request.POST.get('password').strip()#print(username, password)#print(request.POST)if username and password:user = SiteUser.objects.filter(name=username,password=password).first()if user:# ------------核心修改的内容开始request.session['is_login'] = Truerequest.session['user_id'] = user.idrequest.session['username'] = user.name# --------------核心修改的内容结束return redirect('/index/')else:message = "用户名或者密码错误"return render(request, 'login/login.html',{'message': message})else:message = "非法的数据信息"return render(request, 'login/login.html', {'message': message})return render(request, 'login/login.html')
5.2 登出时,清空session信息
# login/views.py
def logout(request):# 如果状态不是登录状态,则无法登出。if request.session.get('is_login'):request.session.flush() # 清空session信息# redirect: 重定向(跳转)return redirect('/login/')
5.3 添加登出的超链接
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>首页</title>
</head>
<body>
<h1>{{ request.session.user_name }}! 欢迎回来!</h1>
<p><a href="/logout/">登出</a>
</p>
</body>
</html>
测试:
5.4 git到本地仓库
git add *
git commit -m "增加session会话与登出"
6、上传到gitee
gitee相当于github的国内版,国内使用速度快
6.1 注册新账号并新建仓库
6.2 上传到gitee仓库准备工作
6.2.1 创建README.md文件(说明文档)
# loginRegister
##项目介绍
##软件架构
##安装教程(基于互联网)
\```bash
git clone xxxx
# 如何生成requirements.txt文件?pip freeze > requirements.txt
pip -r install requirements.txt # pip安装文件中所有的第三方模块
cd xxxx
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver
\```
浏览器访问网址: http://127.0.0.1:9999/index##使用说明
- 可以运行多个平台
6.2.2 生成requirements.txt文件(所需的包)
pip freeze > requirements.txt
6.3 绑定gitee仓库
git remote add origin https://gitee.com/write-me/login-register.git
6.4 上传
Git提交最后一版:上传的版本
上传:
git push --set-upstream origin master -f ## 强制上传
推送失败,原因是我没有开放我的gitee邮箱
解决不公开邮箱问题
上传成功
上传成功
6.5 查看之前版本
6.6 命令行查看分支或增加切换分支
git branch back-morning ##创建新的分支
git branch ##查看当前分支
git log ##查看commit码
git reset --hard c932da0a7dab3 ##版本回退
delete ##删除分支
7、图片验证码
- 为了防止机器人频繁登录网站或者破坏分子恶意登录,很多用户登录和注册系统都提供了图形验证码功
能。 - 在Django中实现图片验证码功能非常简单,有现成的第三方库可以使用,我们不必自己开发(不必重复
造轮子)。这个库叫做django-simple-captcha。 - 具体安装教程:戳我
7.1 安装插件
1 通过pip命令安装: pip install django-simple-captcha2 在settings.py注册captch应用 3 运行数据库迁移 python manage.py migrate4 增加路由策略 urls.py:urlpatterns += [path('captcha/', include('captcha.urls')),
]
7.2 上传gitee仓库
7.3 Django表单
我们前面都是手工在HTML文件中编写表单form元素,然后在views.py的视图函数中接收表单中的用户数据,再编写验证代码进行验证,最后使用ORM进行数据库的增删改查。这样费时费力,整个过程比较复杂,而且有可能写得不太恰当,数据验证也比较麻烦。设想一下,如果我们的表单拥有几十上百个数据字段,有不同的数据特点,如果也使用手工的方式,其效率和正确性都将无法得到保障。有鉴于此,Django在内部集成了一个表单功能,以面向对象的方式,直接使用Python代码生成HTML表单代码,专门帮助我们快速处理表单相关的内容。
Django的表单给我们提供了下面三个主要功能:
1.准备和重构数据用于页面渲染;
2.为数据创建HTML表单元素;
3.接收和处理用户从表单发送过来的数据。编写Django的form表单,非常类似我们在模型系统里编写一个模型。在模型中,一个字段代表数据表的一列,而form表单中的一个字段代表 中的一个 元素。
7.3.1 创建表单模型
# /login/forms.py(新建的文件)from captcha.fields import CaptchaField
from django import forms
class LoginForm(forms.Form):username = forms.CharField(label='用户名', required=True,min_length=4, max_length=128)password = forms.CharField(label="密码", required=True, min_length=4, max_length=10)captcha = CaptchaField(label="验证码")
7.3.2 视图逻辑优化
# login/views.pydef login(request):# 请求方法为POST提交if request.method == 'POST':# 修改1: 实例化表单对象login_form = LoginForm(request.POST)# 修改2: 验证表单数据的合法性if login_form.is_valid():# 修改3:获取表单填写的数据,数据清洗username = login_form.cleaned_data.get('username')password = login_form.cleaned_data.get('password')user = SiteUser.objects.filter(name=username,password=password).first()if user:request.session['is_login'] = Truerequest.session['user_id'] = user.idrequest.session['username'] = user.namereturn redirect('/index/')else:message = "用户名或者密码错误"# 修改4: locals()以字典方式返回当前所有的变量# eg:{'message':'xxxx', 'login_form':'xxx'}return render(request, 'login/login.html', locals())else:message = "填写的登录信息不合法"return render(request, 'login/login.html', locals())# 请求方法是GET请求login_form = LoginForm()return render(request, 'login/login.html', locals())
7.3.3 Template页面优化
# templates/login/login.html(部分修改)<h3 style="text-align: center">用户登录</h3>
# 修改1: 不同的报错,提示不同的信息
{% if login_form.captcha.errors %}
<div class="alert alert-warning" role="alert"><strong>登录失败!</strong> 验证码不正确
</div>
{% elif message %}
<div class="alert alert-warning" role="alert"><strong>登录失败!</strong> {{ message }}
</div>
{% endif %}
<div class="form-group"># 修改2:<label>{{ login_form.username.label }}</label><input type="text" class="form-control" name="username">
</div>
<div class="form-group"># 修改3:<label>{{ login_form.password.label }}</label><input type="password" class="form-control" name="password"><small class="form-text text-muted">密码必须是字母、数字或者特殊符号组成.</small>
</div>
# 修改4: 最重要的,添加验证码表单
<div class="form-group"><label>{{ login_form.captcha.label }}</label>{{ login_form.captcha }}
</div>
全部代码:
<!doctype html>
<html lang="zh-CN">
<head><!-- 必须的 meta 标签 --><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><!-- Bootstrap 的 CSS 文件 --><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css"integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous"><title>用户登录</title>
</head>
<body>
<div class="container"><div class="row"><div class="col-sm"></div><div class="col-sm"><h3 style="text-align: center">用户登录</h3>{% if login_form.captcha.errors %}<div class="alert alert-warning" role="alert"><strong>登录失败!</strong> 验证码不正确</div>{% elif message %}<div class="alert alert-warning" role="alert"><strong>登录失败!</strong> {{ message }}</div>{% endif %}<form action="/login/" method="post">{% csrf_token %}<div class="form-group"><label>{{ login_form.username.label }}</label><input type="text" class="form-control" name="username"></div><div class="form-group"><label>{{ login_form.password.label }}</label><input type="password" class="form-control" name="password"><small class="form-text text-muted">密码必须是字母、数字或者特殊符号组成.</small></div><div class="form-group"><label>{{ login_form.captcha.label }}</label>{{ login_form.captcha }}</div><a href="/register/" class="text-success"><ins>新用户注册</ins></a><button type="submit" class="btn btn-primary float-right">登录</button></form></div><div class="col-sm"></div></div>
</div>
<!-- JavaScript 文件是可选的。从以下两种建议中选择一个即可! --><!-- 选项 1:jQuery 和 Bootstrap 集成包(集成了 Popper) -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js"integrity="sha384-LCPyFKQyML7mqtS+4XytolfqyqSlcbB3bvDuH9vX2sdQMxRonb/M3b9EmhCNNNrV"crossorigin="anonymous"></script><!-- 选项 2:Popper 和 Bootstrap 的 JS 插件各自独立 -->
<!--
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.min.js" integrity="sha384-gRC4eoaRyQ8xv2X6Mnf+eOIrtON3wId3dAkwO0HQX26OrFBoLpjX/XWOJacSiZhL" crossorigin="anonymous"></script>
-->
</body>
</html>
验证:
7.4 git提交下版本
8、 邮箱注册(重点)
8.1 获取授权码并开启SMTP
8.2 配置邮件信息
# loginRegister/settings.py# mail configure(添加信息如下)
EMAIL_HOST = 'smtp.qq.com' # 'smtp.163.com'
EMAIL_PORT = 465 #qq接收和发送有不同的端口(此处是发送)
EMAIL_HOST_USER = 'xxxx' # 你的邮箱地址
#授权码一个是发送邮件IMAP/SMTP,接收邮件使用的是pop3
EMAIL_HOST_PASSWORD = 'xxxxxxx' # 不是邮箱的登录密码,而是授权码(如何获取授权码)
EMAIL_USE_SSL = True # 不开启ssl(qq设置为True,163设置为False)
8.3 交互式环境中测试发送邮件是否成功?
(venv) E:\loginRegister>pip install ipython ## 没安装ipython的安装一下(venv) E:\loginRegister>python manage.py shellIn [1]: from django.core.mail import send_mailIn [2]: from loginRegister.settings import EMAIL_HOST_USERIn [3]: send_mail("测试邮件", "content", EMAIL_HOST_USER,['xxxxxxxx@qq.com']) ## 你邮箱地址
Out[3]: 1
测试成功:
8.4 注册表单
# login/forms.pyclass RegisterForm(forms.Form):username = forms.CharField(label="用户名", required=True, max_length=128)password1 = forms.CharField(label="密码", max_length=256, required=True)password2 = forms.CharField(label="确认密码", max_length=256, required=True)email = forms.EmailField(label="邮箱地址")captcha = CaptchaField(label='验证码')
8.5 实现注册视图
- 如果用户已经登录,则不能注册跳转到首页。
- 如果是GET请求,返回用户注册的html页面。
- 如果是POST请求, 先验证提交的数据是否通过,清洗数据。 接下来判断用户名和邮箱是否已经被
- 注册, 将注册的信息存储到数据库,跳转到登录界面。
- 额外功能: 为了数据的安全性注册时,密码存储到数据库不是明文存储,而是先加密再存储。
# login/views.pyfrom login.forms import LoginForm, RegisterForm
def register(request):# 如果用户已经登录,则不能注册跳转到首页。if request.session.get('is_login', None):return redirect('/index/')# 如果是POST请求if request.method == 'POST':print(request.POST)register_form = RegisterForm(request.POST)message = "请检查填写的内容!"# 先验证提交的数据是否通过if register_form.is_valid():# 清洗数据username = register_form.cleaned_data.get('username')password1 = register_form.cleaned_data.get('password1')password2 = register_form.cleaned_data.get('password2')email = register_form.cleaned_data.get('email')#print(locals())# 接下来判断用户名和邮箱是否已经被注册same_name_user = SiteUser.objects.filter(name=username)#print(same_name_user)if same_name_user:message = '用户名已经存在'return render(request, 'login/register.html', locals())same_email_user = SiteUser.objects.filter(email=email)if same_email_user:message = '该邮箱已经被注册了!'return render(request, 'login/register.html', locals())# 将注册的信息存储到数据库,跳转到登录界面new_user = SiteUser(name=username, password=password1, email=email)new_user.save()return redirect('/login/')# 如果是GET请求,返回用户注册的html页面。register_form = RegisterForm()return render(request, 'login/register.html', locals())
8.6 Template模板的更改
# templates/login/register.html<h3 style="text-align: center">用户注册</h3>
{% if register_form.captcha.errors %}
<div class="alert alert-warning" role="alert"><strong>注册失败!</strong> 验证码不正确
</div>
{% elif message %}
<div class="alert alert-warning" role="alert"><strong>注册失败!</strong> {{ message }}
</div>
{% endif %}<form action="/register/" method="post">{% csrf_token %}<div class="form-group"><label>{{ register_form.username.label }}</label><input type="text" class="form-control" name="username"></div><div class="form-group"><label>{{ register_form.email.label }}</label><input type="email" class="form-control" name="email"></div><div class="form-group"><label>{{ register_form.password1.label }}</label><input type="password" class="form-control" name="password1"><small class="form-text text-muted">密码必须是字母、数字或者特殊符号组成.</small></div><div class="form-group"><label>{{ register_form.password2.label }}</label><input type="password" class="form-control" name="password2"><small class="form-text text-muted">密码必须是字母、数字或者特殊符号组成.</small></div><div class="form-group"><label>{{ register_form.captcha.label }}</label>{{ register_form.captcha }}</div><a href="/login/" class="text-success"><ins>用户登录</ins></a><button type="submit" class="btn btn-primary float-right">注册</button>
</form>
测试:
8.7 注册添加密码加密功能
- 对于如何加密密码,有很多不同的途径,其安全程度也高低不等。这里我们使用Python内置的hashlib库,使用哈希值的方式加密密码,可能安全等级不够高,但足够简单,方便使用。
8.7.1 改动
# 在 login/utils.py 中编写一个hash函数:def hash_code(s, salt='mysite'):# 加点盐h = hashlib.sha256()s += salth.update(s.encode()) # update方法只接收bytes类型return h.hexdigest()
# 在 login/views.py 中修改login和register视图def register(request):# .....省略部分代码new_user = SiteUser(name=username, password=hash_code(password1),email=email)# .....省略部分代码
def login(request):# .....省略部分代码user = SiteUser.objects.filter(name=username,password=hash_code(password)).first()# .....省略部分代码
8.7.2 上传git
git add *
git commit -m "邮箱注册时密码加密处理(hash)"
git push
8.8 邮箱注册确认(是否是真正的邮箱)
- 很自然地,我们会想到如果能用邮件确认的方式对新注册用户进行审查,既安全又正式,也是目前很多站点的做法。
8.8.1 创建模型
- 既然要区分通过和未通过邮件确认的用户,那么必须给用户添加一个是否进行过邮件确认的属性。另外,我们要创建一张新表,用于保存用户的确认码以及注册提交的时间。
# /login/models.pyclass SiteUser(models.Model):# .......has_confirmed = models.BooleanField(default=False, verbose_name="是否邮箱验证")class ConfirmString(models.Model):code = models.CharField(max_length=256, verbose_name="确认码")user = models.OneToOneField('SiteUser', on_delete=models.CASCADE)create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")def __str__(self):return self.user.name + ":" + self.codeclass Meta:ordering = ["-create_time"]verbose_name = "确认码"verbose_name_plural = "确认码"
数据库模型更改,一定要生成迁移脚本和写入数据库。
python manage.py makemigrations
python manage.py migrate
修改一下admin.py文件,方便我们在后台修改和观察数据
# login/admin.py
admin.site.register(ConfirmString)
8.8.2 修改 login/utils.py
#login/utils.py
#make_confirm_string() 是创建确认码对象的方法,代码如下:from django.core.mail import send_mail
from login.models import ConfirmString
from loginRegister import settingsimport datetime
def make_confirm_string(user):"""生成确认码"""print("生成确认码.....")# 获取当前时间now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")code = hash_code(user.name, now)print('in code:',code)ConfirmString.objects.create(code=code, user=user)return code#send_email(email, code) 方法接收两个参数,分别是注册的邮箱和前面生成的哈希值,代码如下:
def send_email(email, code):print('send mail.........')subject = '注册确认邮件'text_content = '''感谢注册,这里是登录注册系统网站!\如果你看到这条消息,说明你的邮箱服务器不提供HTML链接功能,请联系管理员!'''html_content = '''<p>感谢注册<a href="http://{}/confirm/?code={}" target=blank>点击验证</a>,\这里是登录注册系统网站!</p><p>请点击站点链接完成注册确认!</p><p>此链接有效期为{}天!</p>'''.format('127.0.0.1:8000', code, settings.CONFIRM_DAYS)send_mail(subject, text_content,settings.EMAIL_HOST_USER, [email, ], html_message=html_content)
8.8.3 修改视图 login/views.py
##修改的注册视图函数 login/views.pydef register(request):# 如果用户已经登录,则不能注册跳转到首页。if request.session.get('is_login', None):return redirect('/index/')# 如果是POST请求if request.method == 'POST':print(request.POST)register_form = RegisterForm(request.POST)message = "请检查填写的内容!"# 先验证提交的数据是否通过if register_form.is_valid():# 清洗数据username = register_form.cleaned_data.get('username')password1 = register_form.cleaned_data.get('password1')password2 = register_form.cleaned_data.get('password2')email = register_form.cleaned_data.get('email')# 接下来判断用户名和邮箱是否已经被注册same_name_user = SiteUser.objects.filter(name=username)print(same_name_user)if same_name_user:message = '用户名已经存在'return render(request, 'login/register.html', locals())same_email_user = SiteUser.objects.filter(email=email)if same_email_user:message = '该邮箱已经被注册了!'return render(request, 'login/register.html', locals())try:# 将注册的信息存储到数据库,跳转到登录界面new_user = SiteUser(name=username, password=hash_code(password1), email=email)new_user.save()# 生成确认码并发送确认邮件code = make_confirm_string(new_user)print('code:', code)send_email(email, code)message = '请前往邮箱进行确认!'except Exception:new_user.delete()message = '发送邮件失败!'#print(Exception)return render(request, 'login/register.html', locals())else:return redirect('/login/')# 如果是GET请求,返回用户注册的html页面。register_form = RegisterForm()return render(request, 'login/register.html', locals())
8.8.4 提交代码
git add *
git commit -m "用户邮件确认"
git push
Python(18)——Django实战1之可重用注册登录系统(从面到点剖析)相关推荐
- python学习第八天---用Django框架创建可重用注册登录系统
python学习第八天---用Django框架创建可重用注册登录系统 实现的功能 项目开始前的整体规划 搭建环境完成基础配置 创建app 更改语言和时区 数据库表生成 启动开发服务器 浏览器访问,检测 ...
- django完成一个可重用注册登录系统
目录 可重用注册登录系统 项目开始前的思考 搭建项目环境 设计数据库模型 数据库模型文件 设置数据库后端 注册app 生成迁移脚本并写入数据库 测试是否成功 数据库模型后台管理 路由与视图函数框架构建 ...
- Django 可重用注册登录系统
文章目录 一.可重用注册登录系统 1.项目开始前的思考 2.搭建项目环境 3.设计数据库模型 1)数据库模型文件 2)设置数据库后端 3)注册app 4)生成迁移脚本并写入数据库 5)测试是否成功 6 ...
- python注册系统_Python制作简易注册登录系统
Python制作简易注册登录系统 这篇文章主要为大家详细介绍了 Python 简易注册登录系统的制作方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 Python 是一种面向对象.解释型计算机程 ...
- 用Python基础创建一个简单的注册登录系统
在学完Python基础后,是不是有一点想法去做一点好玩的程序呢?如果想可以看看这个注册登录系统,会带给你一些思路. 大家都对登录注册系统司空见惯了吧,我们周围的许多东西都需要登录注册系统,例如很受大众 ...
- 基于python下django框架 实现校园教室图书馆座位预约系统详细设计
前言介绍(开发目的和意义) 本课题主要目标是设计并能够实现一个基于web网页的教室图书馆座位预约系统,整个网站项目使用了B/S架构,基于python的Django框架下开发:管理员通过后台录入信息.管 ...
- Django+bootstrap+注册登录系统
转自:https://www.cnblogs.com/robindong/p/9610057.html Robin_D 博客园 首页 新随笔 联系 订阅 管理 随笔 - 10 文章 - 0 评论 ...
- Python高级爬虫实战,JS解密咪咕音乐登录参数分析
目标:分析咪咕视频登录参数(enpassword.fingerPrint.fingerPrintDetail) 工具:NodeJs + Chrome 开发者工具 许久没有水文了,闲来无事特来混混脸熟 ...
- 计算机毕业设计python基于django的学生考试成绩数据分析与可视化系统
随着社会的逐步发展,计算机网络技术对人们工作.生活影响是全面且深入的.基于计算机网络的管理系统越来越受到人们的欢迎,人们可以通过基于网络的管理系统进行实时数据信息查询.管理数据信息等,给人们的生活.工 ...
最新文章
- 字节二面:GET 请求能上传图片吗?我蒙了。。
- 小白也能看懂的教程:微信小程序在线支付功能开通详细流程(图文介绍)
- 企业安全体系建设方案设计(内附案例)
- VMC Command Line
- Linux根文件系统学习总结
- 汽车abs matlab仿真模糊pid控制
- java loadlibrary_java – System.loadLibrary不起作用.链中的第二个lib的UnsatisfiedLinkError...
- 15万个监控摄像头被黑,医院、学校、监狱都被看得一清二楚
- 01-mysql数据库入门篇-认识mysql-01-05
- MATLAB字符数组和空数组
- vs可以编译python_Python如何进行编译和反编译
- Fragment试手
- 无法启动windows audio服务,错误提示126.
- ValueError: This model has not yet been built. Build the model first by calling `build()` or calling
- Namespace名称空间
- 流程图-时序图-架构图,部署图-拓扑图-ER图-类图-状态图-用例图
- 两个月学习一个月备考托福101分攻略
- Db2性能问题:临时表空间太大,导致连不上数据库
- 一台电脑绿色安装多个版本google Chorme方案
- openlayer制作专题图
热门文章
- win10解决设置默认打开方式不生效问题(双击每次都要选择默认打开程序)
- POI异常:java.lang.NoClassDefFoundError: org.openxmlformats.schemas.spreadsheetml.x2
- 3D体验平台品牌应用——ENOVIA
- 《旅行青蛙》的代码揭秘,攻略,体验
- 【OpenCV 例程200篇】20. 图像的按位运算(cv2.bitwise)
- python uppercase函数_字符串-短rot13函数-Python
- 中医药大学计算机考试题,浙江中医药大学2013年级研究生《计算机应用》期末考试复习题...
- PDF - 使用 Adobe Acrobat 压缩 PDF 大小
- 【Python】使用Zoho/Hotmail给单人/多人发送Email邮件,以及发发送附件
- 【渝粤教育】电大中专Windows操作系统 (2)_1作业 题库