用户管理
用户数据可以说是大部分网站最重要的资产。用户管理就是对用户数据进行增删改查等操作的功能,自然也就非常的重要了。
本章开始学习用户管理的内容,首先从用户登录开始。
在Django中用app来区别不同功能的模块,达到代码隔离和复用。因为用户管理和博客文章的功能不同,因此需要新建一个专门的app。
进入虚拟环境,运行startapp
指令创建新的app:
python manage.py startapp userprofile
查看项目目录,发现已经新生成了userprofile目录及其中的文件了。
再遇表单类
用户登录时,需要填写账户密码等表单数据,因此又要用到Form表单类。
在userprofile
目录中创建表单类的文件forms.py
,编写如下代码:
/userprofile/forms.py
# 引入表单类
from django import forms
# 引入 User 模型
from django.contrib.auth.models import User
# 登录表单,继承了 forms.Form 类
class UserLoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField()
在前面发表文章的模块中,表单类继承了forms.ModelForm
,这个父类适合于需要直接与数据库交互的功能,比如新建、更新数据库的字段等。如果表单将用于直接添加或编辑Django模型,则可以使用 ModelForm
来避免重复书写字段描述。
而forms.Form
则需要手动配置每个字段,它适用于不与数据库进行直接交互的功能。用户登录不需要对数据库进行任何改动,因此直接继承forms.Form
就可以了。
编写视图
用户的登录是比较复杂的功能,好在Django提供了封装好的模块供我们使用。
首先在userprofile/views.py
中写视图函数:
/userprofile/views.py
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login
from django.http import HttpResponse
from .forms import UserLoginForm
# Create your views here.
def user_login(request):
if request.method == 'POST':
user_login_form = UserLoginForm(data=request.POST)
if user_login_form.is_valid():
# .cleaned_data 清洗出合法数据
data = user_login_form.cleaned_data
# 检验账号、密码是否正确匹配数据库中的某个用户
# 如果均匹配则返回这个 user 对象
user = authenticate(username=data['username'], password=data['password'])
if user:
# 将用户数据保存在 session 中,即实现了登录动作
login(request, user)
return redirect("article:article_list")
else:
return HttpResponse("账号或密码输入有误。请重新输入~")
else:
return HttpResponse("账号或密码输入不合法")
elif request.method == 'GET':
user_login_form = UserLoginForm()
context = { 'form': user_login_form }
return render(request, 'userprofile/login.html', context)
else:
return HttpResponse("请使用GET或POST请求数据")
跟发表文章的表单类类似,Form对象的主要任务就是验证数据。调用
is_valid()
方法验证并返回指定数据是否有效的布尔值。Form
不仅负责验证数据,还可以“清洗”它:将其标准化为一致的格式,这个特性使得它允许以各种方式输入特定字段的数据,并且始终产生一致的输出。一旦Form
使用数据创建了一个实例并对其进行了验证,就可以通过cleaned_data
属性访问清洗之后的数据。authenticate()
方法验证用户名称和密码是否匹配,如果是,则将这个用户数据返回。login()
方法实现用户登录,将用户数据保存在session中。
其他的内容就跟发表文章时的技巧类似了。
什么是session
Session在网络应用中,称为“会话控制”,它存储特定用户会话所需的属性及配置信息。
当用户在 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。
Session 最常见的用法就是存储用户的登录数据。
详情看这里:Session百度百科
登录的模板
接着写模板文件。
创建/templates/userprofile/login.html
模板:
/templates/userprofile/login.html
{% extends "base.html" %} {% load staticfiles %}
{% block title %} 登录 {% endblock title %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-12">
<br>
<form method="post" action=".">
{% csrf_token %}
<!-- 账号 -->
<div class="form-group">
<label for="username">账号</label>
<input type="text" class="form-control" id="username" name="username">
</div>
<!-- 密码 -->
<div class="form-group">
<label for="password">密码</label>
<input type="password" class="form-control" id="password" name="password">
</div>
<!-- 提交按钮 -->
<button type="submit" class="btn btn-primary">提交</button>
</form>
</div>
</div>
</div>
{% endblock content %}
内容与使用Form表单类发表新文章非常类似。唯一新知识是输入密码表单的type="password"
,可以让输入密码的时候显示小圆点,避免有人偷窥。
然后我们改写一下tempalates/header.html
,把登录的按钮加进去:
/tempalates/header.html
...
<ul class="navbar-nav">
...
<li class="nav-item">
<a class="nav-link" href="{% url 'article:article_list' %}">文章</a>
</li>
<!-- Django的 if 模板语句 -->
{% if user.is_authenticated %}
<!-- 如果用户已经登录,则显示用户名下拉框 -->
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ user.username }}
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="#">退出登录</a>
</div>
</li>
<!-- 如果用户未登录,则显示 “登录” -->
{% else %}
<li class="nav-item">
<a class="nav-link" href="{% url 'userprofile:login' %}">登录</a>
</li>
<!-- if 语句在这里结束 -->
{% endif %}
</ul>
...
这里使用了新的模板语法:{% if ... %}
,用来判断用户是否已经登录:
- 如果用户已经登录,则显示一个名字为用户名称的下拉框,就像通常的社交网站一样。
- 如果用户未登录,则显示“登录”两个字提醒用户可以点击登录。
is_authenticated
是models.User
类的属性,用于判断用户是否已通过身份验证。
url及其他设置
最后的步骤就是将app配置到项目中去。
创建userprofile/urls.py
文件:
/userprofile/urls.py
from django.urls import path
from . import views
app_name = 'userprofile'
urlpatterns = [
# 用户登录
path('login/', views.user_login, name='login'),
]
配置根路由my_blog/urls.py
:
/my_blog/urls.py
...
urlpatterns = [
...
# 用户管理
path('userprofile/', include('userprofile.urls', namespace='userprofile')),
]
配置my_blog/settings.py
:
my_blog/settings.py
...
INSTALLED_APPS = [
...
'userprofile',
]
...
因为userprofile
这个app并没有改动model,因此不用迁移数据。
OK了,运行服务器,在admin后台中退出登录(找找页面右上角),返回到文章列表页:
点击登录按钮,输入账号和密码(可以故意输错试试会出现什么):
点击提交,将自动回到文章列表页面:
大功告成。
用户的退出
有了用户登录的知识后,用户退出就很简单了。这里就直接给出代码,相信你一定能看懂。
还是先添加用户退出的视图:
/userprofile/views.py
...
# 引入logout模块
from django.contrib.auth import authenticate, login, logout
...
# 用户退出
def user_logout(request):
logout(request)
return redirect("article:article_list")
然后配置/userprofile/urls.py
:
/userprofile/urls.py
...
urlpatterns = [
path('login/', views.user_login, name='login'),
# 用户退出
path('logout/', views.user_logout, name='logout'),
]
在写登录的代码时,已经给用户退出留好了接口,因此只需要改动/templates/header.html
:
/templates/header.html
...
# 改动 href 中的链接指向
<a class="dropdown-item" href='{% url "userprofile:logout" %}'>退出登录</a>
...
保存后刷新页面,点击下拉框中“退出登录”选项,用户就顺利退出了。
总结
本章用到了表单类、if模板语句、用户验证等知识完成了用户管理的登录和退出。
接下来学习如何实现注册和删除。
- 有疑问请在杜赛的个人网站留言,我会尽快回复。
- 或Email私信我:dusaiphoto@foxmail.com
- 项目完整代码:Django_blog_tutorial
转载请告知作者并注明出处。