一、auth组件介绍
在日常的开发中,我们会必定会写的一个功能就是注册,登录,认证,注销且这部分的代码逻辑基本相似。所以django为了我们内置了一个用户认证组件,auth组件,他属于和我们自己创建的app一个级别
二、内置属性方法
auth组件的内置属性与方法都需要数据迁移之后才能使用,当我们数据迁移之后,会在数据库自动生成表格
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())