django注册登录功能的实现(Django搭建网络相册登录与登出)
django注册登录功能的实现(Django搭建网络相册登录与登出)因此首页的 home() 视图函数不仅要处理显示图片的 GET 请求,还要肩负用户登录管理的 POST 请求。GET 请求会将信息暴露在地址栏中,且更容易受到跨域等攻击。安全方法也被称作是幂等的。其他常用的还有 POST 请求,它的使用又分两种情况。一种情况是 POST 请求会修改服务器资源,比如发表新文章、修改用户数据等,另一种情况是请求会携带敏感信息。用户的登入登出就属于第二种情况。
作为个人相册来说,通常只需要简单的用户管理就足够了,原因如下:
- 具有操作资源权限的只有自己,不用考虑诸多网络安全的问题。
- Django 后台提供了丰富的管理能力。
- 评论等需要登录参与的功能可以托管给第三方。(比如 Github 的某些评论插件)
话虽如此,但前台登录退出功能还是要有的,后台总归没那么直观。
因此本章就来简单实现下管理员账户在前台的登入和登出。
后端代码浏览器发起的 HTTP 请求,总共定义了八种请求类型,来表示对指定资源的不同操作方式。比如说前面章节在访问相册主页时,实际上提起的是 GET 请求。GET 请求被称为安全请求,因为按照规范,它不应该在服务器上产生任何结果,也就是不会修改信息。
安全方法也被称作是幂等的。
其他常用的还有 POST 请求,它的使用又分两种情况。
一种情况是 POST 请求会修改服务器资源,比如发表新文章、修改用户数据等,另一种情况是请求会携带敏感信息。用户的登入登出就属于第二种情况。
GET 请求会将信息暴露在地址栏中,且更容易受到跨域等攻击。
因此首页的 home() 视图函数不仅要处理显示图片的 GET 请求,还要肩负用户登录管理的 POST 请求。
像这样修改 views.py 文件:
# /photo/views.py
from django.shortcuts import render
from photo.models import Photo
from django.contrib.auth import authenticate login logout
def home(request):
photos = Photo.objects.all()
context = {'photos': photos}
# 处理登入登出的POST请求
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(request username=username password=password)
# 登入
if user is not None and user.is_superuser:
login(request user)
# 登出
isLogout = request.POST.get('isLogout')
if isLogout == 'True':
logout(request)
return render(request 'photo/list.html' context)
- 请求体 request 包含用户请求的相关信息。request.method 即表明了请求的类型。如果是登录相关的 POST 请求,那么进行下一步的处理。
- request.POST.get() 可获取到 POST 请求中包含的数据。这里就是用户名和密码了。
- 验证用户名、密码是否正确要用 authenticate() 方法。切记不能直接去比较模型中的字符串,因为密码是加密存储的。
- 如果此用户存在并且是管理员,那么则 login() 函数登入。否则不进行处理。
- 请求中还包含一个标志位 isLogout 用来判断用户是想登入还是登出。如果它为真,则 logout() 退出账号。
除此之外其他还是和之前一样了。
接下来是前端部分。
前端代码登录功能一般会将入口放在页眉上,这样可以保证用户可以在任意网页位置进行登入登出操作。
因此修改 header.html 模板文件,变成下面这样:
<!-- /templates/header.html -->
<!-- 导航栏 -->
<nav class="navbar navbar-expand navbar-dark bg-dark">
<div class="container">
<!-- 标志 -->
<a
class="navbar-brand"
href="#"
data-bs-toggle="modal"
data-bs-target="#login"
>
<h2>
Awesome Album
</h2>
</a>
<!-- 登录模态窗 -->
{% if user.is_superuser %}
<ul class="navbar-nav">
<li class="nav-item">
<h2>
<a class="nav-link active" aria-current="page" href="#">
</a>
</h2>
</li>
</ul>
{% endif %}
</div>
</nav>
<!-- 登出 -->
{% if user.is_superuser %}
<div class="modal fade" id="login">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<p>确认退出账号吗?</p>
<form action="{% url 'home' %}" method="post">{% csrf_token %}
<input type="text" id="isLogout" name="isLogout" value="True" hidden>
<button type="submit" class="btn btn-danger">Logout</button>
</form>
</div>
</div>
</div>
</div>
<!-- 登录 -->
{% else %}
<div class="modal fade" id="login">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<form action="{% url 'home' %}" method="post">{% csrf_token %}
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="username">
</div>
<div class="mb-3">
<label for="pwd" class="form-label">Password</label>
<input type="password" class="form-control" id="pwd" name="password">
<div id="passwordHelp" class="form-text">
We'll never share your password with anyone else.
</div>
</div>
<button type="submit" class="btn btn-primary">Login</button>
</form>
</div>
</div>
</div>
</div>
{% endif %}
主要变化就是将导航栏里的网站标题变成了模态窗的入口。页面会根据用户的登录与否,决定显示登入还是登出的模态窗,并同时显示或隐藏“创建新相片”的按钮。
需要注意的点:
- {% if user.is_superuser %} 判断当前是否是管理员用户,与视图中的 user.is_superuser 是相同的。在模板中要包裹在标签内。
- 根据是否是管理员用户,模态窗的具体内容有所不同。这个内容就决定了用户是要登入还是登出。
- 表单元素 <form ...> 中的 action="{% url 'home' %}" 说明此表单提交给当前页面。注意这里的 'home' ,就是当初我们在 path() 中给 url 赋予的名字。method="post" 说明表单提交的是 POST 请求。
- 登出的模态窗有一个 <input ... hidden> 的隐藏数据,此数据不显示给用户,但是会悄悄提交 isLogout="True" 这个数据。就是靠它来确定登入登出状态的。
- 注意每个表单都有 {% csrf_token %} 这么个东西,这是 Django 用来防止跨域攻击的小插件,默认情况下表单必须携带,否则会报 403 错误。
接下来测试。
测试刷新页面,点击页眉中的标题:
提示登录的模态窗就显示出来了。
输入管理员账号密码后,点击提交按钮,有如下变化:
注意看页眉右边出现个加号,这就表示登录成功了。
这个加号用于后续章节上传图片。目前暂时没有功能。
再次点击页眉标题,此时显示的就是提示退出登录的模态窗了。点击红色的提交按钮后,应该就正常退出了账户,右侧的小加号也消失了。
总结本章学习了 Django 中如何处理用户的登录问题的。
你会发现后端的 Python 代码总是比前端 html 代码更少,很大一部分原因是 Django 很好的封装了通用的功能。用户验证就是个例子,你可以在后台中看看用户密码,它是以密文的形式存储的。但是你的代码中完全没管加密与解密的问题,直接调用内置的 authenticate() 函数就搞定了。
登入登出功能也一样,Django 封装了具体的处理方式,你调用 login() 、 logout() 函数即可。
另一方面,你真的不用害怕大量的 html 代码。教程中涉及的内容大概就和 Word 文档排版的难度差不多,唯一区别就是 Word 排版是用鼠标点点点,而 html 将点点点的动作转化成了英文字母。多查阅一定看得懂。
下一章聊聊如何批量上传图片。
点赞 or 吐槽?评论区告诉我!