Day 15 Auth认证组件
一、什么是Auth组件
必须数据库迁移后才能使用,他用的是自己创建的表
Auth模块是Django自带的用户认证模块
我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统。此时我们需要实现包括用户注册、用户登录、用户认证、注销、修改密码等功能,这还真是个麻烦的事情呢。
Django作为一个完美主义者的终极框架,当然也会想到用户的这些痛点。它内置了强大的用户认证系统–auth,它默认使用 auth_user 表来存储用户数据
二、Auth模块常用方法
1.authenticate()
提供了用户认证,也就是验证用户名和密码时候正确,一般是username、password两个关键字参数 字段。如果验证成功,便会返回一个user对象。
authenticate()会在改user对象上设置一个属性来标识后端已经认证了该用户,且该信息在后续登陆过程中是需要的。
user = authenticate(username='usernamer',password='password')
2.login(HttpResponse, user)
这个函数接受一个HttpReponse对象(request),以及一个经过认证的user对象。
这个函数实现一个用户登录的功能。它本质上会在后端为该用户生成相关的session数据
def login(request):
if request.method == 'POST':
name = request.POST.get('name')
password = request.POST.get('password')
# 先获取到用户对象
user = User.objects.get(username=name)
if user.check_password(password): # 如果密码校验成功
auth.login(request, user) # 登录标记
path = request.get_full_path()
if path != '/login/':
obj = redirect(path)
else:
obj = redirect('/index/')
return obj
else:
return HttpResponse('用户名或密码错误!')
return render(request, 'login.html')
3.logout(request)
该函数接受一个HttpResponse对象,无返回值。
当调用该函数的时候,当前请求的session会被全部清除,即使该用户没有登录,使用这个函数也不会报错。
def user_info(request):
user = request.user
all_user = models.User.objects.all()
if request.method == 'POST':
print(request.POST)
tag = request.POST.get('logout')
pk = request.POST.get('pk')
if tag:
auth.logout(request) # 点击退出
return redirect('/login/')
elif pk:
change_user = models.User.objects.get(username=pk)
res = serialize('json', [change_user])[1:-1]
pprint.pprint(res)
return HttpResponse(res)
return render(request, 'usercenter.html', {'user': user, 'all_user': all_user})
4.is_authenticated()
用来判断当前请求是否通过了认证。源码中通过认证默认返回的都是True 匿名用户(没通过的)返回的都是False
5.login_requierd()
auth给我们提供的一个装饰器工具,用来快捷的给某个视图添加登录校验。
@login_required(login_url='/login/')
def user_info(request):
user = request.user
若用户没有登录,则会跳转到django默认的 登录URL '/accounts/login/ ’ 并传递当前访问url的绝对路径 (登陆成功后,会重定向到该路径)。
如果需要自定义登录的URL,则需要在settings.py文件中通过LOGIN_URL进行修改。
示例:
LOGIN_URL = '/login/' # 这里配置成你项目登录页面的路由
6.create_user()
auth提供的一个创建新用户的方法,需要提供必要的参数(username, paaword)等。
from django.contrib.auth.models import User
user = User.objects.create_user(username='用户名',password='密码',email='邮箱',...)
7.create_superuser()
auth提供的一个创建超级用户的方法,需要提欧共必要参数(username, password)等…
from django.contrib.auth.models import User
user = User.objects.create_superuser(username='用户名',password='密码',email='邮箱',...)
8.check_password(password)
auth 提供的一个检查密码是否正确的方法,需要提供当前请求用户的密码。
密码正确返回True,否则返回False。
用法:
ok = user.check_password('密码')
9.set_password(password)
auth 提供的一个修改密码的方法,接收 要设置的新密码 作为参数。
注意:设置完一定要调用用户对象的save方法!!!
用法:
def change_pwd(request):
if request.method == 'POST':
name = request.POST.get('name')
password = request.POST.get('password')
re_password = request.POST.get('repassword')
# 先获取到用户对象
user = User.objects.get(username=name)
if user.check_password(password): # 如果密码校验成功
user.set_password(raw_password=re_password) # 修改密码
user.save() # 保存操作
obj = redirect('/login/')
return obj
else:
return HttpResponse('用户名或密码错误!')
return render(request, 'changepwd.html')
10.user对象的属性
- User对象属性:username, password
- is_staff : 用户是否拥有网站的管理权限
- is_active : 是否允许用户登录, 设置为 False,可以在不删除用户的前提下禁止用户登录。
三、扩展默认的auth_user表
内置的auth_user表,要加字段,加不了,扩展该表
3.1 一对一(OneToOne)
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)
class User(AbstractUser):
phone = models.CharField(max_length=32)
addr = models.CharField(max_length=32)
3.2 通过继承,注意在settings中的配置
使用这种方式,一开始就要用
# settings
# 引用Django自带的User表,继承使用时需要设置
# AUTH_USER_MODEL = "app名.UserInfo"
AUTH_USER_MODEL = "app01.User"
# models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
phone = models.CharField(max_length=32)
四、如果项目一开始没有扩展auth_user表,后期想扩展的操作步骤
1 备份--删库---》重新创建出数据库
2 所有app的数据迁移记录删除migrations下除了__init__.py都删除
3 (重要)去源码中删除auth和admin 这俩app的 3 # pymysql好像不删也可以 migrations下除了__init__.py都删除
4 数据迁移,同步到数据库
5 备份的数据,恢复回去
五、自定义中间表(中介模型)
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 AuthorDatail(models.Model):
nid = models.AutoField(primary_key=True)
telephone = models.BigIntegerField()
birthday = models.DateField()
addr = models.CharField(max_length=64)
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 Publish(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
city = models.CharField(max_length=32)
email = models.EmailField()
# 最土的方式,纯手动建第三张表
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()