Django 用户认证组件和messages消息组件
用户认证组件
Django默认已经提供了认证系统Auth模块,我们认证的时候,会使用auth模块里面给我们提供的表。认证系统包含:
- 用户管理
- 权限
- 用户组
- 密码哈希系统
- 用户登录或内容显示的表单和视图
- 一个可插拔的后台系统 admin
A用户登录后再用同一个客户端登录B用户,session在数据库的记录会被新建且覆盖之前的session,从始至终只有1条数据库记录 而A用户登完,再用A用户账号密码登陆,原始的session在数据库的记录不会发生变化.
前提: 数据库为auth-user表,创建超级用户 python manage.py createsuperuser
(1)Django用户模型类
Django认证系统中提供了用户模型类User保存用户的数据,默认的User包含以下常见的基本字段:
| 字段名 | 字段描述 | 
|---|---|
| username | 必选。150个字符以内。 用户名可能包含字母数字, _,@,+.和-个字符。 | 
| first_name | 可选( blank=True)。 少于等于30个字符。 | 
| last_name | 可选( blank=True)。 少于等于30个字符。 | 
| email | 可选( blank=True)。 邮箱地址。 | 
| password | 必选。 密码的哈希加密串。 (Django 不保存原始密码)。 原始密码可以无限长而且可以包含任意字符。 | 
| is_staff | 布尔值。 设置用户是否可以访问Admin 站点。 | 
| is_active | 布尔值。 指示用户的账号是否激活。 它不是用来控制用户是否能够登录,而是描述一种帐号的使用状态。 | 
| is_superuser | 是否是超级用户。超级用户具有所有权限。 | 
| last_login | 用户最后一次登录的时间。 | 
| date_joined | 账户创建的时间。 当账号创建时,默认设置为当前的date/time。 | 
上面缺少一些字段,所以后面我们会对当前内置的用户模型进行改造,比如说它里面没有手机号字段,后面我们需要加上。
(2)Auth模块内置方法介绍
from django.contrib import auth
| 内置方法名称 | 说明 | 
|---|---|
| authenticate(username, password) | 用于用户认证。将输入的密码转为密文去认证,认证成功返回用户对象,失败则返回None | 
| login(HttpRequest, user) | 用于用户登录。user参数是经过认证的User对象。登录成功后将用户身份信息记录到请求的会话对象中存储。后台使用request.user可获取当前登录的用户对象。如果未登录成功,则request.user得到的是一个匿名用户对象。 | 
| logout(request) | 清除当前请求,注销会话等同于做了session.flush(),但是会清除所有的session_data,如果有其他的用户数据要使用,建议使用del request.session["log_in"],删除部分字段,对其他字段的内容不做影响 | 
(2.1)User模块内置方法介绍
from django.contrib.auth.models import User 注意如果User对象被继承了,则用继承的对象
| 内置方法名称 | 说明 | 
|---|---|
| is_authenticated | 判断当前用户是否经过认证 | 
| is_anonymous | 判断当前用户是否是匿名用户 | 
| create_user() | 创建新用户,至少提供用户名和密码 创建的密码会加密 | 
| create() | create是models下的方法,放在这里比较只是展示他创建的密码是明文的 供参考了解! | 
| set_password(password) | 修改密码 设置用户的密码为给定的原始字符串,并负责密码的。 不会保存User对象。当None为raw_password时,密码将设置为一个不可用的密码。 | 
| check_password(password) | 检查密码是否正确 如果给定的password是用户的真实密码,则返回True,可以在校验用户密码时使用。 | 
详细看官方文档 https://docs.djangoproject.com/zh-hans/3.2/ref/contrib/auth/
(3)内置方法代码示例
user = auth.authenticate(request,username=username,password=password)
if user:
    auth.login(request,user) # 这一步会把认证的用户_id写入到django_session表中,产生一个session_key,后续再中间件中可以通过session_key获取对应加密的session信息,实现后续的cookie认证,权限认证等功能.
    # auth.login的主要功能就是实现了requests.session["user_id"]=user.id   把登录的user对象写入到session中去
    return redirect("/home/page")
(4)auth认证不通过后的装饰器模块
django已经为我们设计好了一个用于此种情况的装饰器:login_requierd()
在setting.py要设置login_url,设置登陆页面,一旦装饰器认证失败返回这个登陆页面
from django.contrib.auth.decorators import login_required
@login_required
def my_view(request):
  ...
(5) )request.user
Django有一个默认中间件,叫做AuthenticationMiddleware,每次请求进来都会去session中去一个userid,取不到的话,赋值request.user = AnonymousUser() , 一个匿名用户对象。
当用户组件auth.login一旦执行,将userid到session中后,再有请求进入Django,将注册的userid对应的user对象赋值给request.user,即再后面的任何视图函数中都可以从request.user中取到该客户端的登录对象。
匿名用户还有下面其他几个属性可以用
id 永远为None
username 永远为空字符串
get_username() 永远返回空字符串
is_staff和is_superuser 永远为false
is_active 永远为false
groups 和user_permission 永远为空
is_annoymous() 返回True
is_authenticated 返回False
set_password(),check_password(),save()和delete()会引发NotImplementError
(6) 自定义用户表
from django.contrib.auth.models import AbstractUser
设置Auth认证模块使用的用户模型为我们自己定义的用户模型
格式:“子应用目录名.模型类名”
AUTH_USER_MODEL = 'users.User'
from django.contrib.auth.models import User,AbstractUser
'''
这里AbstractUser 父类就已经有了username password等一些列的字段了,
其他的只是我们扩展的字段而已
'''
class UserInfo(AbstractUser):
    nid = models.AutoField(primary_key=True)
    telphone = models.CharField(max_length=11, null=True, unique=True)
    avatar = models.FileField(upload_to="avatars/", default="avatars/default.png")
    create_time = models.DateTimeField(verbose_name="创建时间", auto_now_add=True)
    blog = models.OneToOneField(to="Blog", to_field="nid", null=True,on_delete=models.CASCADE)
 
    def __str__(self):
        return self.username
(7) auth中间件功能简介
'django.contrib.auth.middleware.AuthenticationMiddleware'中间件实现的功能
1. user_id = request.session.get("user_id")  # 从session表的user_id字段获取用户id
2. from djang.contrib.auth.models import User
	user = User.object.get(pk=user_id)  # 然后通过用户id和User表获取用户对象
    if user:
        request.user=user				# 把用户对象赋值给request.user
    else:
        request.user=AnonymousUser() 	# 把匿名用户对象赋值给request.user
消息组件
在网页应用中,我们经常需要在处理完表单或其它类型的用户输入后,显示一个一次性的通知信息给用户。
对于这个需求,Django提供了基于Cookie或者会话的消息框架messages,无论是匿名用户还是认证的用户。这个消息框架允许你临时将消息存储在请求中,并在接下来的请求(通常就是下一个请求)中提取它们并显示。每个消息都带有一个特定的level标签,表示其优先级(例如info、 warning或error)。
还可以利用这个一次性的消息实现跳转需求
- 进入页面点击删除按钮
- 跳转到某个实例详情页面后进行二次确认是否删除,点击确认后进行删除
- 再调回到第一步的页面
消息组件的配置
在settings.py中有4处配置
1. 启动messages应用
INSTALLED_APPS = [
    'django.contrib.messages',
]
2. messages框架默认使用的存储后端为sessions。所以Session中间件必须被启用,并出现在Message中间件之前。
MIDDLEWARE = [
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
]
3.TEMPLATES设置中的DjangoTemplates选项包含的'context_processors'配置项要包含'django.contrib.messages.context_processors.messages'。
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
4.MESSAGE_STORAGE默认值是FallbackStorage,是同时会存储在session和cookie,也可以按照需求自行更改
MESSAGE_STORAGE = 'django.contrib.messages.storage.fallback.FallbackStorage'
                   django.contrib.messages.storage.cookie.CookieStorage
                   django.contrib.messages.storage.session.SessionStorage
消息组件的导入和常用方法
from django.contrib import messages 
add_message(request, level, message, extra_tags='', fail_silently=False)[source]
新增一条消息:
from django.contrib import messages
messages.add_message(request, messages.INFO, 'Hello world.')
提供请求对象request(直接用就行),消息级别、消息内容字符串三个参数即可。
或者使用下面的快捷方式
messages.debug(request, '%s SQL statements were executed.' % count)
messages.info(request, 'Three credits remain in your account.')
messages.success(request, 'Profile details updated.')
messages.warning(request, 'Your account expires in three days.')
messages.error(request, 'Document deleted.')
在自定义消息级别时,应小心避免覆盖现有级别。内置级别的值为:
级别	对应整数值
DEBUG	10
INFO	20
SUCCESS	25
WARNING	30
ERROR	40
get_messages(request)[source]
messages可以在视图中用代码获取,也可以在html模版文件获取
messages是一个列表,必须用for标签循环它;
即使你知道只有一条消息,也要迭代messages列表,否则下个请求中,上个请求的消息不会被清除。
对于每一个消息实例,都包含下面的属性,可以在模版或视图中调用:
message: 消息的实际内容文本。不要使用message.message,直接message。
level: 消息级别,一个整数。
tags: 一个字符串,由该消息的所有标签(extra_tags和tags)组合而成,组合时用空格分割开这些标签。
extra_tags: 一个字符串,由该消息的定制标签组合而成,并用空格分割。默认为空。
level_tag: 当前消息级别对应的CSS字符串,前面介绍过。
在你的模板文件中,像下面这样使用:
{% if messages %}
<ul class="messages">
    {% for message in messages %}
    <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
    {% endfor %}
</ul>
{% endif %}
相关说明:
通过if判断是否有消息;
可以通过message.tags拿到每个消息的CSS样式
消息过期机制
默认情况下,如果包含消息的迭代器完成迭代后,当前请求中的消息都将被删除。
如果你不想这么做,想保留这些消息,那么需要显式的指定used参数为False,如下所示:
storage = messages.get_messages(request)
for message in storage:
    do_something_with(message)
storage.used = False
set_level(request, messages.DEBUG)
messages.set_level(request, messages.DEBUG)
messages.debug(request, 'Test message...')
在另外一个视图中修改最小级别为WARNING
messages.set_level(request, messages.WARNING)
messages.success(request, 'Your profile was updated.') # 被忽略,不记录
案例实现
利用这个一次性的消息实现跳转需求
- 进入页面点击删除按钮
- 跳转到某个实例详情页面后进行二次确认是否删除,点击确认后进行删除
- 再调回到第一步的页面
  

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号