Django除了有强大的Admin管理系统,还提供了完善的用户管理系统。整个用户管理系统可分为三大部分:用户信息、用户权限和用户组,在数据库中分别对应数据表auth_user、auth_permission和auth_group。
内置USER用户管理
本节将使用内置的用户管理系统实现用户的注册、登录、修改密码和注销功能。以mysite为例,在项目中创建新的App,命名为user,并在项目的settings.py和urls.py中配置App的信息。
E:\mysite>python manage.py startapp user
#settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'index',
'user',
]
#urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('index.urls')),
path('user/', include('user.urls'))
]
完成user的基本配置后,在App中分别添加urls.py和user.html文件。添加后的目录结构如图:
还要在settings.py中启用该模板文件。
'DIRS': [os.path.join(BASE_DIR, 'user/templates'),
],
App的urls.py设定
在user下的urls.py中设定4个不同的URL地址,分别代表用户登录、注册、修改密码和用户注销:
#user的urls.py
from django.urls import path
from . import views
urlpatterns = [
path('login.html', views.loginView, name='login'),
path('register.html', views.registerView, name='register'),
path('setpassword.html', views.setpasswordView, name='setpassword'),
path('logout.html', views.logoutView, name='logout'),
]
上述URL地址分别对应试图函数loginView、registerView、setpasswordView和logoutView。在编写视图函数之前,首先了解一下user.html模板的代码结构:
{{ title }}
一个模板分别用于实现用户登录、注册和修改密码,该模板是由两个文本输入框和一个按钮所组成的表单,在该表单下分别设置不同链接,分别指向另外两个URL地址。
用户登录
接下来,在views.py中实现用户登录功能,视图函数loginView的代码如下:
#user 的 views.py
from django.shortcuts import render, redirect
from django.contrib.auth.models import User
from django.contrib.auth import login, logout, authenticate
def loginView(request):
#设置标题和两外两个URL链接
title = '登录'
headers = '用户登录'
unit_2 = '/user/register.html'
unit_2_name = '立即注册'
unit_1 = '/user/setpassword.html'
unit_1_name = '修改密码'
if request.method == 'POST':
#用户提交登录,获取登录的用户名和密码
username = request.POST.get('username', '')
password = request.POST.get('password', '')
#首先查找User数据表中有没有该用户,没有提示注册
if User.objects.filter(username=username):
#如果有该用户,则检查用户名和密码是否正确,错误提示重新输入
user = authenticate(username=username, password=password)
if user:
if user.is_active:##判断用户是否被激活,是则由内置函数login完成登录,跳转到主页
login(request, user)
return redirect('/')
else:
tips = '账号密码错误,请重新输入'
else:
tips = '用户不存在,请注册'
return render(request, 'user.html', locals())
以上代码就实现了用户的登录,在整个登录过程中,我们并没有对模型User进行定义,而函数中使用的模型User来自于Django的内置模型,在数据库中对应的数据表为auth_user。该表有以下字段:
字段 | 说明 |
---|---|
id | int类型,数据表主键 |
password | varchar类型,用户密码 |
last_lgoin | datetime类型,最近一次登录时间 |
is_superuser | tinyint类型,是否为超级用户 |
username | varchar类型,用户账号 |
first_name | varchar类型,用户的名字 |
last_name | varchar类型,用户的姓氏 |
电子邮件 | |
is_staff | 判断用户是否可以可以登录Admin系统 |
is_active | tinyint类型,判断该用户的状态是否被激活 |
date_joined | datetime类型,账号的创建时间 |
登陆成功后,页面会自动跳转到index的首页,这里将首页的模板稍做修改,添加以下代码:
#index.html
退出登录
用户名:{{ username }}
然后在index的views.py的视图函数index中传递变量username给模板。
#index 下的 views.py
def index(request):
username = request.user.username
#以下代码省略
#...
这样我们登陆以后就可以看到登陆的用户名。
用户注册
接下来,完成用户注册功能,在user的views.py中编写视图函数registerView,代码如下:
#user的views.py
def registerView(request):
#设置标题和两外两个URL链接
title = '注册'
headers = '用户注册'
unit_2 = 'login.html'
unit_2_name = '立即登录'
unit_1 = 'setpassword.html'
unit_1_name = '修改密码'
if request.method == 'POST':
#获取用户注册的用户名和密码
username = request.POST.get('username', '')
password = request.POST.get('password', '')
#首先查找User数据表中有没有该用户,有则提示用户已存在
if User.objects.filter(username=username):
tips = '用户已存在'
else:
#创建新用户
user = User.objects.create_user(username=username, password=password)
user.save()
tips = '注册成功,请登录'
return render(request, 'user.html', locals())
用户注册和用户登录的流程大致相同,这里需要注意一个问题:
用户登录或者注册的url链接是 '/user/register.html',user前面的 ’/‘ 符号一定不能缺。
修改密码
最后在views.py中编写函数setpasswordView,实现修改密码的功能。
#user 的view.py
def setpasswordView(request):
#设置标题和两外两个URL链接
title = '修改密码'
headers = '密码修改'
unit_2 = '/user/login.html'
unit_2_name = '立即登录'
unit_1 = '/user/register.html'
unit_1_name = '立即注册'
new_password = True#控制模板中新密码的文本框是否出现
if request.method == 'POST':
username = request.POST.get('username', '')
old_password = request.POST.get('password', '')
new_password = request.POST.get('new_password', '')
if User.objects.filter(username=username):#如果查询到用户表中有该用户,则进行下一步,否则提示用户不存在
user = authenticate(username=username, password=old_password)#验证用户和密码是否一致
if user:
user.set_password(new_password)#通过验证则通过set_password内置函数设置新密码
user.save()
tips = '密码修改成功'
else:
tips = '用户名和原密码不一致,请重新输入'
else:
tips = '用户不存在'
return render(request, 'user.html', locals())
密码修改界面比注册和登录界面多出一个文本输入框,该输入框由模板变量new_password控制显示。
上面的密码修改是通过内置函数set_password实现的,而函数set_password是在内置函数make_password的基础上进行封装而来的。内置函数make_password主要是用来实现对用户密码的加密功能,并且该函数可以脱离Auth认证系统单独使用,比如对某些特殊数据进行加密处理等。上述例子中,使用函数make_password实现修改密码的代码部分如下:
from django.contrib.auth.hashers import make_password
#密码加密处理并保存到数据库
dj_pw = make_password(new_password, None, 'pbkdf2_sha256')#加密处理
user.password = dj_pw
user.save()
除了内置函数make_password,还有内置函数check_password,该函数是对加密前的密码与加密后的密码进行验证匹配。判断两者是否为同一密码。在django的shell模式下使用该函数:
>>> from django.contrib.auth.hashers import make_password,check_password
>>> pw = '123456'
>>> dj_pw = make_password(pw, None, 'pbkdf2_sha256')
>>> dj_pw
'pbkdf2_sha256$120000$0ATplZvxaaVN$OIH6gdfMpaYheNtci5iigfod/YIIy4jdkI4UTp60WJM='
>>> check_password(pw, dj_pw)
True
用户注销
用户注销是用户管理系统较为简单的功能,调用内置函数Logout即可实现。代码如下:
#user 的 views.py
def logoutView(request):
logout(request)#退出登录
return redirect('/user/login.html')#跳转到登录页面
实现发送邮件找回密码
上面的密码修改是在用户知道密码的情况下实现的,而在日常应用中,还有一种是用户忘记密码的情况下实现密码修改,也叫密码找回。密码找回首先需要对用户账号进行验证,确认该账号是当前用户所拥有的,验证成功后才能给用户重置密码。本节使用Django内置的邮件功能实现邮箱验证,从而实现密码找回功能。
在实现邮件发送功能之前,需要对邮箱进行相关设置,开启POP3/SMTP服务。以网易163邮箱为例,开通POP3服务时会让你输入一个授权码,这个授权码在后面的开发中需要使用。
接下来需要在settings.py中添加邮箱的相关配置
#mysite 的 settings.py
#邮箱配置信息
#设置django与邮件服务器的连接方式为SSL
EMAIL_USE_SSL = True
#邮件服务器
EMAIL_HOST = 'smtp.163.com'
#邮件服务器端口,若使用SMTP服务器,端口应为465或587
EMAIL_PORT = 465
#发送邮件的账号
EMAIL_HOST_USER = '[email protected]'
#SMTP服务密码,客户端的授权密码
EMAIL_HOST_PASSWORD = 'fe*********'
#设置默认发送邮件的账号
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
完成邮箱相关配置后,先到user的urls.py中设置密码找回的URL地址信息,添加以下路径
#user 的 urls.py
path('findpassword.html', views.findpasswordView, name='findpassword'),
添加好URL地址信息后,我们到视图模块中编写视图函数findpasswordView,代码如下:
#user 的 views.py
def findpasswordView(request):
button = '获取验证码'
new_password = False
if request.method == 'POST':
username = request.POST.get('username','')
verificationCode = request.POST.get('verificationCode', '')
password = request.POST.get('password','')
#验证用户是否存在
user = User.objects.filter(username=username)
#用户不存在
if not user:
tips = '用户 ' + username + ' 不存在'
else:
#用户存在,则判断验证码是否发送
#如果session中没有验证码信息,则发送验证码并将验证码写入session
if not request.session.get('verificationCode', ''):
button = '重置密码'
tips = '验证码已发送'
new_password = True#展示新密码文本输入框
verificationCode = str(random.randint(1000,9999))#生成随机4位数验证码
request.session['verificationCode'] = verificationCode#将验证码写入session
user[0].email_user('找回密码', verificationCode)#通过内置函数email_user向用户发送验证码邮件
#匹配输入的验证码是否正确
elif verificationCode == request.session.get('verificationCode'):
#密码加密处理并保存到数据库
dj_pw = make_password(password, None, 'pbkdf2_sha256')
user[0].password = dj_pw
user[0].save()
del request.session['verificationCode']#删除session中的验证码信息
tips = '密码已重置'
else:
tips = '验证码错误,请重新获取'
new_password = False
del request.session['verificationCode']
return render(request, 'user1.html', locals())
这里用一个新的模板user1.html,与上面的user.html稍有不同。
找回密码
密码找回
{% if tips %}
{{ tips }}
{% endif %}
输入http://127.0.0.1:8000/user/findpassword.html进入密码找回界面
。
如果不输入用户名或者输入不存在的用户名则会提示用户不存在。
我们输入用户名user来尝试以下,
可以看到,网页显示验证码已发送,但是在这之前,需要在数据表中插入用户user的邮箱信息,否则邮件是无法发送出去的。
打开邮箱可以看到验证码已经发送成功,下面就是输入验证码更改密码。
输入完以后点击重置密码,可以看到密码已重置
Django除了内置函数email_user实现邮件发送之外,还另外提供多种邮件发送方法,我们在shell模式下讲解:
使用 send_mail 实现邮件发送
>>> from django.core.mail import send_mail
>>> from django.conf import settings
#获取settings.py的配置信息
>>> from_email = settings.DEFAULT_FROM_EMAIL
#发送邮件,接收邮件以列表表示,说明可设置多个接收对象
>>> send_mail('邮件头', '邮件主题', from_email, ['[email protected]'])
1
使用send_mass_mail实现多封邮件同时发送
>>> from django.core.mail import send_mass_mail
>>> from django.conf import settings
>>> from_email = settings.DEFAULT_FROM_EMAIL
>>> message1 = ('邮件头1','邮件主题1', from_email, ['[email protected]'])
>>> message2 = ('邮件头2','邮件主题2', from_email, ['[email protected]'])
#多封邮件信息以元组形式封装发送
>>> send_mass_mail((message1,message2), fail_silently=False)
2
使用EmailMultiAlternatives 实现邮件发送
>>> from django.core.mail import EmailMultiAlternatives
>>> from django.conf import settings
>>> from_email = settings.DEFAULT_FROM_EMAIL
>>> content = '这是一封很重要的邮件.
'
>>> msg = EmailMultiAlternatives('邮件头', content, from_email, ['[email protected]'])
#将正文设置为HTML格式
>>> msg.content_subtype = 'html'
#可选,对正文内容进行补充和添加
>>> msg.attach_alternative('是的很重要...', 'text/html')
#可选,添加附件
>>> msg.attach_file('E://test.txt')
#发送
>>> msg.send()
1
扩展User模型
在开发过程中,模型User的字段可能满足不了复杂的开发需求。现在大多数网站的用户信息都有用户的手机号码、QQ号码和微信号等一系列个人信息。为了满足各种需求,Django还提供了4种模型扩展方法。一般情况下,建议使用AbstractUser扩展模型User,因为该方式对原有模型User影响较少而且无须额外创建数据表。
下面以mysite项目为例讲解如何使用AbstractUser扩展模型User。
首先在MySQL中找到项目所使用的数据库,并清除该数据库中全部的数据表,在user的models.py文件中定义模型MyUser,代码如下:
#user 的 models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class MyUser(AbstractUser):
qq = models.CharField('QQ号码', max_length=16)
weChat = models.CharField('微信账号', max_length=100)
mobile = models.CharField('手机号码', max_length=11)
# 设置返回值
def __str__(self):
return self.username
模型MyUser继承自AbstractUser类,AbstractUser类已有内置模型User的字段属性,因此模型MyUser具有模型User的全部属性。在执行数据迁移(创建数据表)之前,必须要在项目的settings.py中配置相关信息。
#settings.py
AUTH_USER_MODEL = 'user.MyUser'
配置信息是将内置模型User替换成user定义的模型MyUser,若没有设置配置信息,在创建数据表的时候,会分别创建数据表auth_user 和 user_myuser。
在项目命令行下执行数据迁移:
python manage.py makemigrations
python manage.py migrate
完成数据迁移后,打开数据库查看数据表信息,可以发现内置模型User的数据表auth_user改为数据表user_myuser,并且数据表user_myuser的字段除了具有内置模型User的字段,还额外增加了自定义的字段,如图所示:接着使用
python manage.py createsuperuser
创建超级用户并登录Admin后台管理系统。我们会发现认证与授权没有用户信息表,这是因为模型MyUser是在user的models.py中定义的。若将模型MyUser展示在后台系统,则要在user的admin.py中定义相关的数据对象:
#admin.py
from django.contrib import admin
from .models import MyUser
from django.contrib.auth.admin import UserAdmin
from django.utils.translation import gettext_lazy as gl
@admin.register(MyUser)
class MyUserAdmin(UserAdmin):
list_display = ['username', 'email', 'mobile', 'qq', 'weChat']
#修改用户时,在个人信息里添加 'mobile 、'qq'、'weChat'的信息录入
#将源码的UserAdmin.fieldsets转换成列表格式
fieldsets = list(UserAdmin.fieldsets)
#重写UserAdmin的fieldsets,添加'mobile'、'qq'、'weChat'的信息录入
fieldsets[1] = (gl('Personal info'), {'fields':('first_name','last_name','email','mobile','qq','weChat')})
#__init__.py
#设置App(user)的中文名
from django.apps import AppConfig
import os
# 修改app在admin后台显示名称
# default_app_config的值来自apps.py的类名
default_app_config = 'user.IndexConfig'
# 获取当前app的命名
def get_current_app_name(_file):
return os.path.split(os.path.dirname(_file))[-1]
# 重写类IndexConfig
class IndexConfig(AppConfig):
name = get_current_app_name(__file__)
verbose_name = '用户管理'
重启mysite项目并进入Admin后台,可以在界面看到模型MyUser生成的用户信息表。
进入用户信息表,并修改某个用户信息时,发现用户信息的修改界面出现用户的手机号码、QQ号码和微信号码的文本输入框,这是由MyUserAdmin类中重写属性fieldsets实现的。
[图片上传失败...(image-ab68e8-1583646371682)]
上述admin.py定义的MyUserAdmin继承自UserAdmin,UserAdmin是内置模型User的Admin数据对象,因此,在定义MyUserAdmin时,直接继承UserAdmin,并通过重写某些属性,可以快速开发扩展模型MyUser的Admin后台数据对象。
除了继承UserAdmin的Admin数据对象之外,还可以在表单中继承内置模型User所定义的表单类。内置的表单类forms.py说明如下:
表单类 | 表单字段 | 说明 |
---|---|---|
UserCreationForm | username,password1,password2 | 创建新的用户信息 |
UserChangeForm | password, 模型User全部字段 | 修改已有的用户信息 |
AuthenticationForm | username,password | 用户登录时所触发的验证功能 |
PasswordResetForm | 将重置密码通过发送邮件方式实现密码找回 | |
SetPasswordForm | password1,password2 | 修改或新增用户密码,设置密码时,无须对旧密码进行验证 |
PasswordChangeForm | old_password,newpassword1,new_password2 | 继承SetPasswordForm,修改密码前需要对旧密码进行验证 |
AdminPasswordChangeForm | password1,password2 | 用于Admin后台修改用户密码 |
上述内置的表单累都涉及模型User的字段,说明这些表单是在内置模型User的基础上实现的。因此,我们为扩展模型MyUser定义相关的表单累可以继承上述的表单类。以UserCreationForm为例,使用表单类UserCreationForm实现用户注册功能。在user中创建form.py文件:
#user 的 form.py
from django.contrib.auth.forms import UserCreationForm
from .models import MyUser
class MyUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = MyUser
# 在注册界面添加邮箱、手机号码、微信号码和QQ号码
fields = UserCreationForm.Meta.fields + ('email', 'mobile', 'weChat', 'qq')
然后在模板user.html和视图函数registerView中编写以下代码:
#模板user.html
用户注册
MyDjango Auth
{% if tips %}
{{ tips }}
{% endif %}
#user 的 views.py
from django.shortcuts import render
from .form import MyUserCreationForm
# 使用表单实现用户注册
def registerView(request):
if request.method == 'POST':
user = MyUserCreationForm(request.POST)
if user.is_valid():
user.save()
tips = '注册成功'
user = MyUserCreationForm()
else:
user = MyUserCreationForm()
return render(request, 'user.html',locals())
然后在浏览器上访问http://127.0.0.1:8000/user/register.html,就实现了用户注册的功能。
[图片上传失败...(image-b46a-1583646371681)]
用户权限
用户权限主要是对不同的用户设置不同的功能使用权限,而每个功能主要以模型来划分。数据库中的数据表auth_permission的每条数据信息就代表项目中某个模型的某个权限:
设置用户权限实质上是对数据表user_myuser和auth_permission之间的数据设置多对多关系。
从整个项目的数据表可以看到,用户、用户权限和用户组分别对应数据表user_myuser、auth_permission和auth_group.无论是设置用户权限、设置用户所属用户组还是设置用户组的权限,其实质都是对两个数据表之间的数据建立多对多的数据关系:
- 数据表user_myuser_user_permissions:管理数据表user_myuser和auth_permission之间的多对多关系,实现用户权限设置
- 数据表user_myuser_groups:管理数据表user_myuser和auth_group之间的多对多关系,实现在用户组设置用户
- 数据表auth_group_permissions:管理数据表auth_group和auth_permission之间的多对多关系,实现用户组设置权限。
需要注意的是:用户权限的设置只适用于非超级用户。我们在shell模式下简单介绍下用户权限设置。
#导入模型MyUser
>>> from user.models import MyUser
#查询用户信息,filter查询返回列表格式,因此设置列表索引获取User对象
>>> user = MyUser.objects.filter(username='user')[0]
#判断当前用户是否具有权限add_product
#index.add_product是固定写法,index为项目的App名, add_product是数据表auth_permission的字段codename
>>> user.has_perm('index.add_product')
False
#导入模型Permission
>>> from django.contrib.auth.models import Permission
#在权限管理表获取权限add_product的数据对象permission
>>> permission = Permission.objects.filter(codename='add_product')[0]
#对当前用户对象user 设置权限add_product
>>> user.user_permissions.add(permission)
#重新查询用户对象,判断用户权限
>>> user = MyUser.objects.filter(username='user')[0]
>>> user.has_perm('index.add_product')
True
上述代码为用户新增了一条权限,打开数据表user_myuser_user_permissions可以看到新增了一条数据。
myuser_id和permission_id分别是数据表user_myuser和auth_permission的主键。
除了添加权限外,还可以对用户的权限进行删除和查询。
>>> user = MyUser.objects.filter(username='user')[0]
>>> permission = Permission.objects.filter(codename='add_product')[0]
#删除某条权限
>>> user.user_permissions.remove(permission)
#重新查询用户对象,判断权限是否被删除
>>> user = MyUser.objects.filter(username='user')[0]
>>> user.has_perm('index.add_product')
False
#清空当前用户全部权限
>>> user.user_permissions.clear()
#将上述删除的权限添加到数据表中再查询当前权限
>>> user.user_permissions.add(permission)
>>> user.user_permissions.values()
>>>
自定义用户权限
一般情况下,每个模型默认有增(add)、改(change)、删(delete)权限,但实际开发中,可能要对某个模型设置特殊的权限,比如设置访问权限,这时候我们就需要在定义模型的时候,在模型的Meta中设置自定义权限。
对index的模型Product重新定义:
#index 的 models.py
class Product(models.Model):
id = models.AutoField('序号', primary_key=True)
name = models.CharField('名称',max_length=50)
weight = models.CharField('重量',max_length=20)
size = models.CharField('尺寸',max_length=20)
type = models.ForeignKey(Type, on_delete=models.CASCADE,verbose_name='产品类型')
# 设置返回值
def __str__(self):
return self.name
class Meta:
#自定义权限
permissions = (
('visit_product', 'Can visit Product'),
)
定义模型Product时,通过重写父类models.Model的permissions属性可实现自定义用户权限。该属性以元组或列表的数据格式表示,每个元素代表一个权限,也以元组或列表表示。一个权限中含有两个元素,分别是数据表auth_permission的codename和name字段。
在数据库中清除原有的数据表,重新执行数据迁移,执行完成后,打开数据表auth_permission,可以找到自定义权限visit_Product。
设置网页的访问权限
上面定义了自定义用户权限,下面介绍如何在实际开发中使用用户权限。确保数据表auth_permission已自定义权限visit_Product,数据表user_myuser分别创建了一个超级用户和一个普通用户。
首先在user 的urls.py定义URL信息
#user 的urls.py
from django.urls import path
from . import views
urlpatterns = [
#用户登录
path('login.html', views.loginView, name='login'),
#用户注册
path('register.html', views.registerView, name='register'),
#退出登录
path('logout.html', views.logoutView, name='logout')
]
然后编写对应的视图函数
from django.shortcuts import render,redirect
from .models import MyUser
from django.contrib.auth.models import Permission
from django.contrib.auth import login, authenticate, logout
def loginView(request):
tips = '请登录'
title = '用户登录'
if request.method == 'POST':
username = request.POST.get('username', '')
password = request.POST.get('password', '')
if MyUser.objects.filter(username=username):
user = authenticate(username=username, password=password)
if user:
if user.is_active:
# 登录当前用户
login(request, user)
return redirect('/')
else:
tips = '账号密码错误,请重新输入'
else:
tips = '用户不存在,请注册'
return render(request, 'user.html', locals())
# 用户注册
def registerView(request):
title = '用户注册'
if request.method == 'POST':
username = request.POST.get('username', '')
password = request.POST.get('password', '')
if MyUser.objects.filter(username=username):
tips = '用户已存在'
else:
user = MyUser.objects.create_user(username=username, password=password)
user.save()
# 添加权限
permission = Permission.objects.filter(codename='visit_Product')[0]
user.user_permissions.add(permission)
return redirect('/user/login.html')
return render(request, 'user.html', locals())
# 退出登录
def logoutView(request):
logout(request)
return redirect('/')
最后编写模板文件user.html
user 的 templates 的 user.html
{{ title }}
MyDjango Auth
{% if tips %}
{{ tips }}
{% endif %}
上述代码主要实现一个简单的操作流程,流程顺序为用户注册--->用户登录--->访问首页。
在user中实现了用户的权限设置,接着在index中实现用户权限的校验。首先编写index的urls.py文件:
#index 的 urls.py
from django.urls import path
from . import views
urlpatterns = [
# 首页的URL
path('', views.index),
]
然后编写对应的视图函数:
#index的views.py
from django.shortcuts import render
from django.contrib.auth.decorators import login_required, permission_required
# 使用login_required和permission_required分别对用户登录验证和用户权限验证
@login_required(login_url='/user/login.html')
@permission_required(perm='index.visit_Product', login_url='/user/login.html')
def index(request):
return render(request, 'index.html', locals())
在视图函数index中使用了装饰起login_required和permission_required,分别对当前用户的登录状态和用户权限进行校验。
- login_required:设置用户登录访问权限,如果当前用户尚未登录而直接访问首页,程序自动跳转到登录界面,只有用户完成登录后才能访问首页。login_required的参数有redirect_field_name和login_url
参数redirect_field_name:默认值是next,当登录成功后,程序自动跳转回之前浏览的网页
参数login_url:设置登录界面的URL地址,默认值是settings.py的属性LOGIN_URL,而属性LOGIN_URL需要开发者自行在settings.py中配置。
- permission_required:验证当前用户是否拥有相应的权限。若用户没有使用权限,程序会跳转到登录界面或抛出异常。permission_required的参数如下:
参数perm : 必须参数,判断当前用户是否拥有权限,参数为固定格式,如上例中index为项目的App名,visit_product来自数据表auth_permission的字段codename
参数login_url: 设置登录界面的URL地址,默认值为None,若不设置参数,验证失败后会抛出404异常。
参数 raise_exception :设置抛出异常,默认值为False
装饰器permission_required的作用与内置函数has_perm相同,上述代码也可以使用函数has_perm实现装饰器permission_required的功能。
# 使用函数has_perm实现装饰器permission_required功能
from django.shortcuts import render, redirect
@login_required(login_url='/user/login.html')
def index(request):
user = request.user
if user.has_perm('index.visit_Product'):
return render(request, 'index.html', locals())
else:
return redirect('/user/login.html')
最后再模板index.html中实现用户权限判断。模板的
#index 的 templates 的 index.html
从上述例子可以看到,项目的user主要实现权限的设置功能,项目的index主要实现权限的使用,权限的使用主要判断当前用户是否具有权限的使用资格,而权限的判断可以从视图函数或模板语法实现。
设置用户组
用户组就是对用户进行分组管理,其作用是在权限控制中批量对用户的权限进行分配,而不用一个个的按用户分配,节省维护的工作量。
设置用户组分为两个步骤:设置用户组的权限和设置用户组的用户。
我们在数据表auth_group中创建一个管理员用户组。用户组可以创建任意多个。
然后再shell模式下简单学习用户组的权限配置
#导入内置模型Group和Permission
>>> from django.contrib.auth.models import Group
>>> from django.contrib.auth.models import Permission
#获取某个权限对象permission
>>> permission = Permission.objects.get(codename='visit_product')
#获取某个用户组对象group
>>> group = Group.objects.get(id=1)
#将权限permission添加到用户组group中
>>> group.permissions.add(permission)
#当然也能删除某个权限
>>> group.permissions.remove(permission)
#删除全部权限
>>> group.permissions.clear()
然后我们再学习如何将用户分配到用户组。
#导入模型MyUser和Group
>>> from user.models import MyUser
>>> from django.contrib.auth.models import Group
#获取用户对象user,对象user代表用户名为user的数据信息
>>> user = MyUser.objects.get(username='user')
#获取用户组对象group,对象group代表用户组(管理员)的数据信息
>>> group = Group.objects.get(id=1)
#将用户添加到用户组
>>> user.groups.add(group)
#删除用户组某一用户
>>> user.groups.remove(group)
#清空用户组全部用户
>>> user.groups.clear()