可重用注册登录系统
1、思考
需求分析
- 注册(绑定邮箱,手机号,微信,QQ等)
- 登录
- 注销
思考(Django项目的流程和生命周期)
- 路由配置(URL CONF):负责不同页面的跳转
- 视图配置(Views):负责各种业务逻辑和流程
- 数据库模型(Models):负责数据的存储交互和处理
- 模板(Templates):负责美化浏览器端的界面展示,提高用户体验和用户友好性。
2、搭建项目环境
创建App
python manage.py startapp login
修改语言时区
settings.py
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
数据库表生成
python manage.py migrate # 将迁移文件内容写入数据库中,并生成数据库表
python manage.py createsuperuser #创建后台管理员
启动开发服务器
- 命令启动
python manage.py runserver
- 运行配置中设置
工具栏中Run–>edit configurations–>选中本项目–>设置本机主机号和端口号–>OK–>Run该项目即可
浏览器访问网址是否成功
https://127.0.0.1:8000 #测试首页
https://127.0.0.1:8000/admin #测试后台管理界面
git提交项目代码到本地仓库
git init
# 安装插件ignore,并生成python上传git项目需要忽略内容的文件.ignore
git add *
# 添加修改到缓存区
git commit -m "xxxxx"
#将暂存区的代码提交到本地git仓库
git log
# 查看历史提交记录
3、设计数据库模型
作为一个可供用户登录和注册的项目,需要获取并保存用户的相关信息。所以至少需要一张用户表User,表的逻辑结构如下:
- 用户名:必填,不超过128个字符,且唯一(unique)
- 密码:必填,不超过256个字符
- 邮箱:使用Django框架的内置邮箱类型,且唯一
- 性别:使用choice,只能选择男或女,默认值为未知(default)
- 创建时间:用户创建时间
注:
auto_now_add=True为添加时的时间,更新对象时不会有变动 - 修改时间:用户最后一次修改时间
注:
auto_add=True无论添加还是修改对象,时间都会计算为修改时间 - 最后一次登录时间:最后一次登录的时间
注:
null=True,数据库中该字段为NULL,即允许空值
blank=Flase(默认)的话,字段为空则会抛异常;和数据验证(表单验证)有关。
数据库模型文件
models.py
class SiteUser(models.Model):
'''
用户的数据库模型,注册、登录都能使用
'''
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_chioce = (
(0, "未知"),
(1, "男"),
(2, "女"),
)
gender = models.IntegerField(choices=gender_chioce, default=0, verbose_name="性别")
create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
modify_time = models.DateTimeField(auto_now=True, verbose_name="最后一次修改时间")
last_login_time = models.DateTimeField(null=True, blank=True, verbose_name="最后一次登录时间")
# null针对数据库层面,当执行sql语句时
# blank针对于表单层面
def __str__(self):
return self.name
class Meta:
# db_table = ''
# ordering =['-create_time']
verbose_name = "网站用户管理"
verbose_name_plural = verbose_name
设置数据库后端
Django支持MySQL,Sqlite,Oracle等数据库,本例使用默认的Sqlite数据库
注册App
settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'login',
]
生成迁移脚本并写入数据库
python manage.py makemigrations #生成迁移文件
python manage.py migrate #将迁移文件内容写入数据库中,并生成数据库表
生成迁移文件
测试
在生成迁移文件的同时,Models中设置的对象属性会自动生成数据库汇总的表
打开db.sqlite3
数据库模型后台管理
login/admin.py
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:8000/admin/
4、路由、视图函数及模板的框架搭建
路由设计
URL | 视图Views | 模板 | 功能 |
---|---|---|---|
/index/ | login.views.index | index.html | 首页 |
/login/ | login.views.login | login.html | 登录界面 |
register | login.views.register | register.html | 注册界面 |
logout | login.views.logout | 无需返回页面 | 登出见面 |
访问策略
- 未登录状态:访问登录、注册、登出时全部跳转至登录界面
- 已登录状态:访问登录跳转至首页
- 已登录状态:不允许直接访问注册界面,需要先登出才能注册
- 登出状态:自动跳转到登录界面
路由配置
- 主路由配置文件
# loginRegister/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('login.urls')) #访问的网址没有前缀时,访问login这个子应用的路由文件
]
- 子路由配置文件(login子应用)
# login/urls.py
from django.urls import path, include
from . import views
urlpatterns = [
path('lindex/,views.index,name="index")
path('login/,views.login,name="login")
path('register/,views.register,name="register")
path('logout/,views.logout,name="logout")
]
视图函数
从子路由配置文件寻找路由到视图函数寻找相应的业务逻辑
# login/views.py
from django.shortcuts import render, redirect
def index(request):
return render(request,'index.html'),
def login(request):
return render(request,'login.html'),
def register(request):
return render(request,'register.html'),
def logout(request):
#redirect 重定向,即跳转到指定界面
return redirect(request,'/login/'),
模板Templates
视图函数中的HTML界面由模板Templates来实现,通过渲染将页面最终呈现在浏览器页面上
- 首页界面
# 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:8000/index
- http://127.0.0.1:8000/login
- http://127.0.0.1:8000/register
5、前端界面设计与优化
舒适美观的界面人见人爱,需要HTML加持CSS和JS来辅助。
Bootstrap 是全球最受欢迎的前端框架,用于构建响应式、移动设备优先的网站。
6、完善登录的视图函数
- 修改1、有message信息则显示,没有则不显示
- 修改2、提交登录信息时,以post方式提供给/login/对应的视图函数处理
- 修改3、Django提供了csrf防攻击机制,添加该信息则可以顺利访问登录界面
- 修改4、表单填写的内容POST提交存储的key值名称,eg:{“username”:“你填的用户名”}
#templates/login/login.html
<div class="col-sm-3 col-sm-3">
<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">
<!-- 当用户单击登录按钮执行以post方法访问LOGIN路由对应的视图函数-->
# 修改3、Django提供了csrf防攻击机制,添加该信息则可以顺利访问登录界面
{% csrf_token %}
<div class="form-group">
# 修改4、表单填写的内容POST提交存储的key值名称,eg:{"username":"你填的用户名"}
<label>用户名</label>
<input type="text" class="form-control" name="username">
<small id="emailHelp" class="form-text text-muted">密码必须由字母数字特殊字符组成</small>
</div>
<div class="form-group">
<label>密码</label>
<input type="password" class="form-control" name="password">
</div>
<a href="{% url 'login:register' %}"><ins style="color: green">新用户注册</ins></a>
<button type="submit" class="btn btn-primary float-right">登录</button>
</form>
</div>
<div class="col-sm"></div>
视图函数的完善和处理
def login(request):
if request.method == "POST":
username = request.POST.get('username')[0].strip()
password = request.POST.get('password')[0].strip()
print(username, password)
if username and password:
# 用户名是否存在
# 密码和数据库中存储的密码是否一致
user = SiteUser.objects.filter(name=username, password=password).first()
if user:
# return redirect('/index/')
return render(request, 'login/index.html')
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')
测试
运行服务器,测试网址:
- http://127.0.0.1:8000/index
- http://127.0.0.1:8000/login
- http://127.0.0.1:8000/register
7、session会话与登录的视图函数
- 登录成功,存储登录的用户信息到session中
# login/views.py
def login(request):
if request.method == "POST":
username = request.POST.get('username')[0].strip()
password = request.POST.get('password')[0].strip()
print(username, password)
if username and password:
# 用户名是否存在
# 密码和数据库中存储的密码是否一致
user = SiteUser.objects.filter(name=username, password=password).first()
if user:
# 1、 核心修改的内容
request.session['is_login'] = True
request.session['user_id'] = user.id
request.session['username'] = user.name
return render(request, 'login/index.html')
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')
- 登出时,清空session信息
# login/views.py
def logout(request):
if request.session.get('is_login'):
request.session.flush() #清空session信息
return render(request, 'login/login.html')
- 在首页添加登出的超链接并测试
# templates/login/index.html
<body>
<h1>你好!{{ request.session.username }},这是测试界面</h1>
<a href="/logout/"><strong style="font-size: 20px">登出</strong></a>
</body>
测试
运行服务器,测试网址:
- http://127.0.0.1:8000/index