django auth
1. auth组件介绍
Auth模块是Django自带的用户认证模块:
我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统。此时我们需要实现包括用户注册、用户登录、用户认证、注销、修改密码等功能,这还真是个麻烦的事情呢。
Django作为一个完美主义者的终极框架,当然也会想到用户的这些痛点。它内置了强大的用户认证系统--auth,它默认使用 auth_user 表来存储用户数据。
2. auth模块常用方法
from django.contrib import auth
1. authenticate
提供了用户认证功能,即验证用户名以及密码是否正确,一般需要username 、password两个关键字参数。
如果认证成功(用户名和密码正确有效),便会返回一个 User 对象。
authenticate()会在该 User 对象上设置一个属性来标识后端已经认证了该用户,且该信息在后续的登录过程中是需要的。
user = authenticate(username='usernamer',password='password')
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')
user=auth.authenticate(request,username=name,password=password)
if user:
return HttpResponse('登录成功')
else:
return HttpResponse('用户名或密码错误')
2. login
该函数接受一个HttpRequest对象,以及一个经过认证的User对象 表示用户登录了
该函数实现一个用户登录的功能。它本质上会在后端为该用户生成相关session数据。
auth.login(request,user)
from django.contrib.auth import authenticate, login
def my_view(request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
...
else:
...
3. logout
该函数接受一个HttpRequest对象,无返回值。
当调用该函数时,当前请求的session信息会全部清除。该用户即使没有登录,使用该函数也不会报错。
from django.contrib.auth import logout
def logout_view(request):
auth.logout(request)
return redirect('/index/')
4. is_authenticated
用来判断当前请求是否通过了认证 即判断用户是否登录
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
auth 给我们提供的一个装饰器工具,用来快捷的给某个视图添加登录校验。
装饰器,装饰在视图函数上,只要没有登录,就进不来
from django.contrib.auth.decorators import login_required
@login_required
def my_view(request):
...
@login_required(login_url='/login/')
若用户没有登录,则会跳转到django默认的 登录URL '/accounts/login/ ' 并传递当前访问url的绝对路径 (登陆成功后,会重定向到该路径)。
如果需要自定义登录的URL,则需要在settings.py文件中通过LOGIN_URL进行修改。
示例:
LOGIN_URL = '/login/'
6. create_user/superuser
auth 提供的一个创建新用户的方法,需要提供必要参数(username、password)等
auth 提供的一个创建新的超级用户的方法,需要提供必要参数(username、password)等
from django.contrib.auth.models import User
user=User.objects.create_user(username=name,password=password)
user=User.objects.create_superuser(username=name,password=password)
7. check_password
auth 提供的一个检查密码是否正确的方法,需要提供当前请求用户的密码
密码正确返回True,否则返回False
ok = user.check_password('密码')
user = User.objects.filter(username=name).first()
flag=user.check_password(password)
8. set_password
auth 提供的一个修改密码的方法,接收 要设置的新密码 作为参数
注意:设置完一定要调用用户对象的save方法
user.set_password(password='')
user.save()
@login_required
def set_password(request):
user = request.user
err_msg = ''
if request.method == 'POST':
old_password = request.POST.get('old_password', '')
new_password = request.POST.get('new_password', '')
repeat_password = request.POST.get('repeat_password', '')
if user.check_password(old_password):
if not new_password:
err_msg = '新密码不能为空'
elif new_password != repeat_password:
err_msg = '两次密码不一致'
else:
user.set_password(new_password)
user.save()
return redirect("/login/")
else:
err_msg = '原密码输入错误'
content = {
'err_msg': err_msg,
}
return render(request, 'set_password.html', content)
3. User对象属性
username password
is_staff: 用户是否拥有网站的管理权限,是否可以登录到后台管理
is_superuser: 是否是超级管理员(如果is_staff=1,可以任意增删查改任何表数据)
is_active: 是否允许用户登录, 设置为 False
可以在不删除用户的前提下禁止用户登录(三次密码输入错误禁用用户)
4. 扩展默认的auth_user表
内置的认证系统这么好用,但是auth_user表字段都是固定的那几个,我在项目中没法拿来直接使用啊!
比如,我想要加一个存储用户手机号的字段,怎么办?
聪明的你可能会想到新建另外一张表然后通过一对一和内置的auth_user表关联,这样虽然能满足要求但是有没有更好的实现方式呢?
我们可以通过继承内置的 AbstractUser 类,来定义一个自己的Model类。
这样既能根据项目需求灵活的设计用户表,又能使用Django强大的认证系统了。
方式一: 一对一
方式二: 通过继承
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
phone = models.CharField(max_length=32)
addr = models.CharField(max_length=32)
AUTH_USER_MODEL = "app01.User"
按上面的方式扩展了内置的auth_user表之后,一定要在settings.py中告诉Django,我现在使用我新定义的UserInfo表来做用户认证。写法如下:
AUTH_USER_MODEL = "app名.UserInfo"
一旦我们指定了新的认证系统所使用的表,我们就需要重新在数据库中创建该表,而不能继续使用原来默认的auth_user表了
1. 备份--删库---》重新创建出数据库
2. 所有app的数据迁移记录删除migrations下除了__init__.py都删除
3. 去源码中删除auth和admin 这俩app的migrations下除了__init__.py都删除
4. 数据迁移,同步到数据库
5. 备份的数据,恢复回去
5. 自定义中间表(中介模型)
1. 示例一
-默认使用ManyToMany,自动创建
-使用中介模型
-即手动创建第三张表,又要使用好用的查询
-完全自己写第三张表
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)
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()
import os
if __name__ == '__main__':
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day76.settings")
import django
django.setup()
from app01 import models
book = models.Book.objects.get(pk=1)
book.authors.add(1,2)
2. 示例二
利用orm自动帮我们创建第三张关系表
class Book(models.Model):
name = models.CharField(max_length=32)
authors = models.ManyToManyField(to='Author')
class Author(models.Model):
name = models.CharField(max_length=32)
"""
优点:代码不需要你写 非常的方便 还支持orm提供操作第三张关系表的方法...
不足之处:第三张关系表的扩展性极差(没有办法额外添加字段...)
"""
class Book(models.Model):
name = models.CharField(max_length=32)
class Author(models.Model):
name = models.CharField(max_length=32)
class Book2Author(models.Model):
book_id = models.ForeignKey(to='Book')
author_id = models.ForeignKey(to='Author')
"""
优点:第三张表完全取决于你自己进行额外的扩展
不足之处:需要写的代码较多,不能够再使用orm提供的简单的方法
不建议使用该方式
"""
class Book(models.Model):
name = models.CharField(max_length=32)
authors = models.ManyToManyField(to='Author',
through='Book2Author',
through_fields=('book','author')
)
class Author(models.Model):
name = models.CharField(max_length=32)
class Book2Author(models.Model):
book = models.ForeignKey(to='Book')
author = models.ForeignKey(to='Author')
"""
through_fields字段先后顺序
判断的本质:
通过第三张表查询对应的表 需要用到哪个字段就把哪个字段放前面
简化判断
当前表是谁 就把对应的关联字段放前面
半自动
可以使用orm的正反向查询 但是没法使用add,set,remove,clear这四个方法
"""
需要掌握的是全自动和半自动 为了扩展性更高 一般我们都会采用半自动