Django-Auth组件

一、auth组件介绍

在日常的开发中,我们会必定会写的一个功能就是注册,登录,认证,注销且这部分的代码逻辑基本相似。所以django为了我们内置了一个用户认证组件,auth组件,他属于和我们自己创建的app一个级别

二、内置属性方法

auth组件的内置属性与方法都需要数据迁移之后才能使用,当我们数据迁移之后,会在数据库自动生成表格

image-20201026160047374

image-20201026160619899

1.authenticate用户认证

提供了用户认证功能,即验证用户名以及密码是否正确,一般需要username 、password两个关键字参数。

如果认证成功(用户名和密码正确有效),便会返回一个 User 对象。

authenticate()会在该 User 对象上设置一个属性来标识后端已经认证了该用户,且该信息在后续的登录过程中是需要的。

from django.contrib import auth

def login(request):
    if request.method=='GET':
        return render(request,'login.html')
    else:
        name=request.POST.get('name')
        password=request.POST.get('password') # 明文
        # 第一个参数必须是request对象
        user=auth.authenticate(request,username=name,password=password)
        if user:
            return HttpResponse('登录成功')
        else:
            return HttpResponse('用户名或密码错误')

2.login

# 表示用户登录了,使用该方法后做了下面两件事
# 1 存了用户的session
# 2 以后所有的视图函数,都可以使用request.user,它就是当前登录用户
auth.login(request,user)

3.logout

def logout(request):
    # 后续再访问视图函数,就没有当前登录用户了request.user(他会产生一个匿名用户AnonymousUser)
    auth.logout(request)
    return redirect('/index/')

4.is_authenticated

is_authenticated,返回True或者False,判断用户是否登录

# 用在视图中
if request.user.is_authenticated:
    print('用户登录了')
else:
    print('用户没有登录,匿名用户')

# 更多是用在模板中
{% if request.user.is_authenticated %}
    {{ request.user.username }} 登录成功
{% else %}
    <a href="/login/">请登录</a>
{% endif %}

5.login_requierd

是一个装饰器,装饰再视图函数上,只要没有登录,进我们指定的页面。(一般为登录页面),登录成功后悔自动重定向到当前页面

若只写@login_required,则会跳转到django默认的登录URL '/accounts/login/ ' 并传递当前访问url的绝对路径 (登陆成功后,会重定向到该路径)。

from django.contrib.auth.decorators import login_required

@login_required(login_url='/login/')
def order(request):
    return HttpResponse('ok')

6.create_user

# 使用内置的create_user或者create_superuser方法
user=User.objects.create_user(username=name,password=password)
user=User.objects.create_superuser(username=name,password=password)

7.check_password

有了用户,校验密码是否正确

# 先获取到用户对象
user = User.objects.filter(username=name).first()
# 判断密码是否正确
flag=user.check_password(password)

8.set_password

修改密码

def change_password(request):
    if request.method == 'GET':
        return render(request, 'change_pwd.html')
    else:
        old_pwd = request.POST.get('old_pwd')
        new_pwd = request.POST.get('new_pwd')
        re_new_pwd = request.POST.get('re_new_pwd')
        if request.user.check_password(old_pwd):
            # 密码正确再修改
            request.user.set_password(new_pwd)
            # 要手动保存
            request.user.save()
            return redirect('/login/')
        else:
            return HttpResponse('原密码错误')

9.User对象的属性

is_staff:用户是否拥有网站的管理权限,是否可以登录到后台管理
is_superuser:是否是超级管理员(如果is_staff=1,可以任意增删查改任何表数据)
is_active:是否允许用户登录, 设置为 False,可以在不删除用户的前提下禁止用户登录(三次密码输入错误禁用用户)

三、扩展默认的auth_user表

默认的auth_user表的字段有些情况下不够使用,比如我们需要记录用户的手机号,家庭地址等等,那么就需要扩展该表。

在扩展的时候,都是在我们之前使用的models

方式一:一对一

from django.contrib.auth.models import User

class UserDetail(models.Model):
    phone = models.CharField(max_length=32)
    addr = models.CharField(max_length=32)
    user= models.OneToOneField(to=User)

方式二:继承

# 步骤一:setting中配置
AUTH_USER_MODEL = "app01.User"
# 步骤二:写类,使用这种方式,一开始创建表的时候就得使用
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
    # 也可以重写原来的字段,比如觉得名字字段太短了,username = models.CharField(max_length=128)
    phone = models.CharField(max_length=32)
    addr = models.CharField(max_length=32)

1.后期扩展

如果项目一开始没有扩展auth_user表,后期想扩展的操作步骤

1 备份--删库---》重新创建出数据库
2 所有app的数据迁移记录删除migrations下除了__init__.py都删除
3 (重要)去源码中删除auth和admin 这俩app的migrations下除了__init__.py都删除
4 数据迁移,同步到数据库
5 备份的数据,恢复回去

四、自定义中间表(中介模型)

1.默认使用ManyToMany,自动创建

2.完全自己手写第三张表

class AuthorToBook(models.Model):
    nid = models.AutoField(primary_key=True)
    book_id = models.ForeignKey(to=Book, to_field='nid', on_delete=models.CASCADE)
    author_id = models.ForeignKey(to=Author, to_field='nid', on_delete=models.CASCADE)
    date=models.DecimalField()
    
# 在book表,author表中,就不需要再添加ForeignKey字段了
# 手动创建表后添加等,需要自己手动写了。因为这其实是一张自己创建出来的表,在我们逻辑层面和其他表有关系,但是对于数据库本身来说没关系。
models.AuthorToBook.objects.create(book_id_id=1,author_id_id=1)
models.AuthorToBook.objects.create(book_id_id=1,author_id_id=2)

3.使用中介模型

使用中介模型之后,原本多读多的方法,add,set,clear,remove都不能使用了,只能查询。但是查询是有所简便,不需要再经过中间表了。

# 使用中介模型,即是在手动创建的基础上,在manytomany的关联字段上添加两个参数:
# through='AuthorToBook',through_fields=('book_id','author_id')
class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    author_detail = models.OneToOneField(to='AuthorDatail', to_field='nid', unique=True, on_delete=models.CASCADE)

class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish_date = models.DateField()

    publish = models.ForeignKey(to='Publish', to_field='nid', on_delete=models.CASCADE)
    # 当前在哪个表中,元组中的第一个参数就是 表明_id
    authors=models.ManyToManyField(to='Author',through='AuthorToBook',through_fields=('book_id','author_id'))
    def __str__(self):
        return self.name

class AuthorToBook(models.Model):
    nid = models.AutoField(primary_key=True)
    book_id = models.ForeignKey(to=Book, to_field='nid', on_delete=models.CASCADE)
    author_id = models.ForeignKey(to=Author, to_field='nid', on_delete=models.CASCADE)
    date=models.DecimalField()
    
# 中介模型的查询,更为简单
book = models.Book.objects.get(pk=1)
print(book.authors.all())
posted @ 2020-12-01 11:02  王寄鱼  阅读(89)  评论(0编辑  收藏  举报