文章目录

  • 前言
  • 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之可重用注册登录系统(从面到点剖析)相关推荐

  1. python学习第八天---用Django框架创建可重用注册登录系统

    python学习第八天---用Django框架创建可重用注册登录系统 实现的功能 项目开始前的整体规划 搭建环境完成基础配置 创建app 更改语言和时区 数据库表生成 启动开发服务器 浏览器访问,检测 ...

  2. django完成一个可重用注册登录系统

    目录 可重用注册登录系统 项目开始前的思考 搭建项目环境 设计数据库模型 数据库模型文件 设置数据库后端 注册app 生成迁移脚本并写入数据库 测试是否成功 数据库模型后台管理 路由与视图函数框架构建 ...

  3. Django 可重用注册登录系统

    文章目录 一.可重用注册登录系统 1.项目开始前的思考 2.搭建项目环境 3.设计数据库模型 1)数据库模型文件 2)设置数据库后端 3)注册app 4)生成迁移脚本并写入数据库 5)测试是否成功 6 ...

  4. python注册系统_Python制作简易注册登录系统

    Python制作简易注册登录系统 这篇文章主要为大家详细介绍了 Python 简易注册登录系统的制作方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 Python 是一种面向对象.解释型计算机程 ...

  5. 用Python基础创建一个简单的注册登录系统

    在学完Python基础后,是不是有一点想法去做一点好玩的程序呢?如果想可以看看这个注册登录系统,会带给你一些思路. 大家都对登录注册系统司空见惯了吧,我们周围的许多东西都需要登录注册系统,例如很受大众 ...

  6. 基于python下django框架 实现校园教室图书馆座位预约系统详细设计

    前言介绍(开发目的和意义) 本课题主要目标是设计并能够实现一个基于web网页的教室图书馆座位预约系统,整个网站项目使用了B/S架构,基于python的Django框架下开发:管理员通过后台录入信息.管 ...

  7. Django+bootstrap+注册登录系统

    转自:https://www.cnblogs.com/robindong/p/9610057.html Robin_D 博客园 首页 新随笔 联系 订阅 管理 随笔 - 10  文章 - 0  评论 ...

  8. Python高级爬虫实战,JS解密咪咕音乐登录参数分析

    目标:分析咪咕视频登录参数(enpassword.fingerPrint.fingerPrintDetail) 工具:NodeJs + Chrome 开发者工具 许久没有水文了,闲来无事特来混混脸熟 ...

  9. 计算机毕业设计python基于django的学生考试成绩数据分析与可视化系统

    随着社会的逐步发展,计算机网络技术对人们工作.生活影响是全面且深入的.基于计算机网络的管理系统越来越受到人们的欢迎,人们可以通过基于网络的管理系统进行实时数据信息查询.管理数据信息等,给人们的生活.工 ...

最新文章

  1. 字节二面:GET 请求能上传图片吗?我蒙了。。
  2. 小白也能看懂的教程:微信小程序在线支付功能开通详细流程(图文介绍)
  3. 企业安全体系建设方案设计(内附案例)
  4. VMC Command Line
  5. Linux根文件系统学习总结
  6. 汽车abs matlab仿真模糊pid控制
  7. java loadlibrary_java – System.loadLibrary不起作用.链中的第二个lib的UnsatisfiedLinkError...
  8. 15万个监控摄像头被黑,医院、学校、监狱都被看得一清二楚
  9. 01-mysql数据库入门篇-认识mysql-01-05
  10. MATLAB字符数组和空数组
  11. vs可以编译python_Python如何进行编译和反编译
  12. Fragment试手
  13. 无法启动windows audio服务,错误提示126.
  14. ValueError: This model has not yet been built. Build the model first by calling `build()` or calling
  15. Namespace名称空间
  16. 流程图-时序图-架构图,部署图-拓扑图-ER图-类图-状态图-用例图
  17. 两个月学习一个月备考托福101分攻略
  18. Db2性能问题:临时表空间太大,导致连不上数据库
  19. 一台电脑绿色安装多个版本google Chorme方案
  20. openlayer制作专题图

热门文章

  1. win10解决设置默认打开方式不生效问题(双击每次都要选择默认打开程序)
  2. POI异常:java.lang.NoClassDefFoundError: org.openxmlformats.schemas.spreadsheetml.x2
  3. 3D体验平台品牌应用——ENOVIA
  4. 《旅行青蛙》的代码揭秘,攻略,体验
  5. 【OpenCV 例程200篇】20. 图像的按位运算(cv2.bitwise)
  6. python uppercase函数_字符串-短rot13函数-Python
  7. 中医药大学计算机考试题,浙江中医药大学2013年级研究生《计算机应用》期末考试复习题...
  8. PDF - 使用 Adobe Acrobat 压缩 PDF 大小
  9. 【Python】使用Zoho/Hotmail给单人/多人发送Email邮件,以及发发送附件
  10. 【渝粤教育】电大中专Windows操作系统 (2)_1作业 题库