第十四篇:Django之Auth认证模块【完结撒花】

第十四篇:Django之Auth认证模块

一、什么是Auth认证模块?

我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统。此时我们需要实现包括用户注册、用户登录、用户认证、注销、修改密码等功能。

Django内部内置了用户认证系统Auth,它默认使用 auth_user 表来存储用户数据。

其实我们在创建好一个django项目之后直接执行数据库迁移命令会自动生成很多表,其中就包括auth_user表。

django在启动之后就可以直接访问admin路由,需要输入用户名和密码,数据参考的就是auth_user表,并且还必须是管理员用户才能进入。

步骤:
1、先使用数据迁移命令创建auth_user表
2、使用 python3 manage.py createsuperuser 创建超级用户(管理员)
   (django使用auth_user表完成用户相关的所有功能)

auth_user表中的结构如下。

第十四篇:Django之Auth认证模块【完结撒花】

创建超级用户。

第十四篇:Django之Auth认证模块【完结撒花】

然后我们可以使用创建好的账户登录管理员系统。界面如下所示。

第十四篇:Django之Auth认证模块【完结撒花】

二、Auth模块常用方法?

1、登录功能实现

代码如下。

"""urls.py"""
urlpatterns = [
    url(r‘^admin/‘, admin.site.urls),
    # 登录功能
    url(r‘^login/‘, views.login),
    # home
    url(r‘^home/‘, views.home)
]


"""views.py"""
from django.contrib import auth
# 登录功能
def login(request):
    if request.method == ‘POST‘:
        username = request.POST.get(‘username‘)
        password = request.POST.get(‘password‘)
        """
        去用户表auth_user中校验数据,现在遇到两个问题
        1.表如何获取?
        2.密码如何比对?
        """
        user_obj = auth.authenticate(username=username, password=password)  # 类似于filter
        """
        1.自动查找auth_user标签
        2.自动给密码加密再比对
        该方法注意事项
            括号内必须同时传入用户名和密码
            不能只传用户名(一步就帮你筛选出用户对象)
        """
        # print(user_obj)  # yangyi (其实是用户对象,类内部定义了__str__方法,打印用户名而已)如果没有,返回None
        # print(user_obj.username)  # yangyi
        # print(user_obj.password)  # pbkdf2_sha256$36000$3vnqqEiG5sCe$rAQHyBT1ze0rtk1if7gi+++3GUQH+LVvwOYsWZJtryE=
        # 判断用户是否存在
        if user_obj:
            # 保存用户状态
            auth.login(request, user_obj) # 类似于request.session[key] = user_obj
            # 主要执行了该方法 你就可以在任何地方通过request.user获取到当前登陆的用户对象
            return redirect(‘/home/‘)
    return render(request, ‘login.html‘)

# home
def home(request):
    return HttpResponse(‘data from home‘)


"""login.html"""
<h1 class="text-center">登录功能</h1>
<form action="" method="post">
    {% csrf_token %}
    <p>username:<input type="text" name="username" class="form-control"></p>
    <p>password:<input type="password" name="password" class="form-control"></p>
    <input type="submit" class="btn btn-block btn-primary">
</form>

登录成功之后,浏览器底部显示。

第十四篇:Django之Auth认证模块【完结撒花】

总结:

# 1.比对用户名和密码是否正确
user_obj = auth.authenticate(request,username=username,password=password)
# 括号内必须同时传入用户名和密码
print(user_obj)  # 用户对象  yangyi   数据不符合则返回None
print(user_obj.username)  # yangyi
print(user_obj.password)  # 密文

# 2.保存用户状态
auth.login(request,user_obj)  # 类似于request.session[key] = user_obj
# 主要执行了该方法 你就可以在任何地方通过request.user获取到当前登陆的用户对象

2、检验用户是否登录

def home(request):
    """自动去django_session里面查找对应的用户对象给你封装到request.user中"""
    print(request.user)  # yangyi(用户对象) 如果没登陆,返回AnonymousUser(匿名用户)
    """
    到了这里,便可根据request.user的不同而作判断了,但是django提供了更简单的方法 is_authenticated()
    """
    print(request.user.is_authenticated())  # True  # 判断用户是否登陆认证
    return HttpResponse(‘data from home‘)

总结:

# 1.获取当前登陆用户
request.user

# 2.判断当前用户是否登陆
request.user.is_authenticated()

3、校验用户是否登陆装饰器

auth提供了封装好的登录认证装饰器,极为方便【不用自己手动写】

from django.contrib.auth.decorators import login_required
# @login_required  # 如果没有登陆,则403forbidden
@login_required(login_url=‘/login/‘)  # 如果没有登陆,进行跳转到/login/页面
def index(request):
    return HttpResponse(‘data from index‘)

总结:

from django.contrib.auth.decorators import login_required

# 局部配置
@login_required(login_url=‘/login/‘) 
# 全局配置
LOGIN_URL = ‘/login/‘  # 之后就可以只写login_required

"""
1.如果局部和全局都有,那么谁起作用?
  局部 > 全局
2.局部和全局哪个好呢?
  全局的好处在于无需重复写代码,但是跳转的页面却很单一
  局部的好处在于不同的视图函数在用户没有登陆的情况下可以跳转到不同的页面
"""

4、修改密码

"""urls.py"""
urlpatterns = [
    url(r‘^admin/‘, admin.site.urls),
    # 登录功能
    url(r‘^login/‘, views.login),
    # home
    url(r‘^home/‘, views.home),
    url(r‘^index/‘, views.index),
    # 修改密码
    url(r‘set_password‘, views.set_password)
]


"""views.py"""
@login_required(login_url=‘/login/‘)
def set_password(request):
    if request.method == ‘POST‘:
        # 拿到数据
        old_password = request.POST.get(‘old_password‘)
        new_password = request.POST.get(‘new_password‘)
        confirm_password = request.POST.get(‘confirm_password‘)
        # 先校验两次密码是否一致
        if new_password == confirm_password:
            # 校验旧密码是否正确
            """这里出现了一个问题,自己传来的密码是明文,如何和数据库中的密文进行对比?"""
            is_right = request.user.check_password(old_password)
            if is_right:
                # 修改密码
                request.user.set_password(new_password)  # 仅仅是在修改对象的属性
                request.user.save()  # 这一步才是真正的操作数据库
        return redirect(‘/login/‘)
    return render(request, ‘set_password.html‘, locals())


"""set_password.html"""
<h1 class="text-center">修改密码</h1>
<form action="" method="post">
    {% csrf_token %}
{#可以直接传入value内容{{ request.user.username }}#}
    <p>username:<input type="text" name="username" class="form-control" disabled value="{{ request.user.username }}"></p>
    <p>old_password:<input type="password" name="old_password" class="form-control"></p>
    <p>new_password:<input type="password" name="new_password" class="form-control"></p>
    <p>confirm_password:<input type="password" name="confirm_password" class="form-control"></p>
    <input type="submit" class="btn btn-block btn-primary">
</form>

总结:

# 1.比对原密码
request.user.check_password(old_password)

# 7.修改密码
request.user.set_password(new_password)  # 仅仅是在修改对象的属性
request.user.save()  # 这一步才是真正的操作数据库

5、注销用户

# 注销用户
def logout(request):
    auth.logout(request)  # 类似于request.session.flush()
    return redirect(‘/login/‘)

6、注册用户

"""views.py"""
from django.contrib.auth.models import User
# 注册功能
def register(request):
    if request.method == ‘POST‘:
        username = request.POST.get(‘username‘)
        password = request.POST.get(‘password‘)
        """尝试1:create  不能用create 密码没有加密处理"""
        # User.objects.create(username=username, password=password)
        """方法1:create_user 创建普通用户"""
        # User.objects.create_user(username=username, password=password)
        """方法2:create_superuser 创建超级用户"""
        User.objects.create_superuser(username=username, email=‘123@qq.com‘, password=password)
    return render(request, ‘register.html‘)

第十四篇:Django之Auth认证模块【完结撒花】

第十四篇:Django之Auth认证模块【完结撒花】

总结:

"""尝试1:create  不能用create 密码没有加密处理"""
User.objects.create(username=username, password=password)
"""方法1:create_user 创建普通用户"""
User.objects.create_user(username=username, password=password)
"""方法2:create_superuser 创建超级用户"""
User.objects.create_superuser(username=username, email=‘123@qq.com‘, password=password)

三、如何扩展auth_user表?

我们在实际项目中,可能经常会发现auth_user字段不能够满足项目的要求,那么我们该如何拓展auth_user中的字段呢?

1、一对一关系

"""第一种方法:一对一关系(不推荐)"""
from django.db import models
from django.contrib.auth.models import User

class UserDetail(models.Model):
    phone = models.BigIntegerField()
    user = models.OneToOneField(to=‘User‘)

2、面向对象的继承

我们看第二种方式,面向对象的继承,打开源码,我们便可以发现,Uset表继承了AbstractUser这个类。

第十四篇:Django之Auth认证模块【完结撒花】

而AbstractUser中,便是很熟悉的auth_user字段。所以我们可以直接继承AbstractUser类,替换掉auth_user表。

第十四篇:Django之Auth认证模块【完结撒花】

"""第二种方法:面向对象的继承"""
class UserInfo(AbstractUser):
    phone = models.BigIntegerField()
# 第二种方式的注意事项
"""
如果继承了AbstractUser,那么在执行数据库迁移命令的时候auth_user表就不会再创建出来了
而UserInfo表中会出现auth_user所有的字段外加自己扩展的字段,这么做的好处在于你能够直接点击你自己的表更加快速的完成操作及扩展
而不用使用orm跨表查询	
"""

前提:
 1.在继承之前没有执行过数据库迁移命令
   即auth_user没有被创建,如果当前库已经创建了那么就必须重新换一个库。
 2.继承的类里面不要覆盖AbstractUser里面的字段名
   表里面有的字段都不要动,只扩展额外字段即可
 3.需要在配置文件中告诉django你要用UserInfo替代auth_user(******)
    # auth表配置(注意不用写app01.models.UserInfo)
	AUTH_USER_MODEL = ‘app01.UserInfo‘	

    
"""总结:"""
如果自己写表替代了auth_user,那么auth模块的功能还是照常使用,只不过参考的表页由原来的auth_user变成了UserInfo。

我们使用mysql数据库尝试第二种方法。

第十四篇:Django之Auth认证模块【完结撒花】

第十四篇:Django之Auth认证模块【完结撒花】

第十四篇:Django之Auth认证模块【完结撒花】

上一篇:使用idea创建mybatis的时候找不到配置的XML,但是已经配置了,而且路径也是正确的。


下一篇:pd.set_option