Django自带的用户认证
auth模块
from django.contrib import auth
备注:使用auth模块时,我们默认使用Django提供的auth_user表,创建数据时,可以使用命令行来创建超级用户:
命令行:在项目的根目录下输入:python manage.py createsuperuser 回车提示输入用户名:输入用户名后,回车,输入邮箱地址,可以不填,继续回车,输入密码:输入密码时,密码必须是数字和字母组成,并且不能少于八位,否则会报错,其他的信息可以不填。
django.contrib.auth中提供了许多方法,这里主要介绍其中的三个:
authenticate()
提供了用户认证,即验证用户名以及密码是否正确,一般需要username password两个关键字参数
如果认证信息有效,会返回一个 User 对象。authenticate()会在User 对象上设置一个属性来标识后端已经认证了该用户,且该信息在后续的登录过程中是需要的。
当我们试图登陆一个从数据库中直接取出来不经过authenticate()的User对象时会报错!!!
user = authenticate(username='theuser',password='thepassword')
login(HttpRequest, user)
该函数接受一个HttpRequest对象,以及一个认证了的User对象
备注:auth.login方法将校验通过的用户封装到request中,这样在request的生命周期我们都可以使用request.user得到这个用户的对象,不管是在视图函数还是在模板语言中都可以使用request.user 然后在 .字段属性 来取到需要的内容。
此函数使用django的session框架给某个已认证的用户附加上session id等信息。
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)
# Redirect to a success page.
...
else:
# Return an 'invalid login' error message.
...
logout(request) 注销用户
from django.contrib.auth import logout def logout_view(request):
logout(request)
# Redirect to a success page.
该函数接受一个HttpRequest对象,无返回值。当调用该函数时,当前请求的session信息会全部清除。该用户即使没有登录,使用该函数也不会报错。
备注:注销用户后,直接访问这个路径,还可以登录,但是我们可以print(request.user),当用户通过校验登录时,得到的是一个具体的用户对象,当注销时,再次访问时,就会输出AnonymousUser(是一个类 <class 'django.utils.functional.SimpleLazyObject'>),意为匿名用户,可以通过这个处理一些判断。
user对象的 is_authenticated()
要求:
1 用户登陆后才能访问某些页面,
2 如果用户没有登录就访问该页面的话直接跳到登录页面
3 用户在跳转的登陆界面中完成登陆后,自动访问跳转到之前访问的地址
方法1:
def my_view(request):
if not request.user.is_authenticated():
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
方法2:
django已经为我们设计好了一个用于此种情况的装饰器:login_required()
from django.contrib.auth.decorators import login_required @login_required
def my_view(request):
...
若用户没有登录,则会跳转到django默认的 登录URL '/accounts/login/ ' (这个值可以在settings.py文件中通过LOGIN_URL进行修改)。并传递 当前访问url的绝对路径 (登陆成功后,会重定向到该路径)。
User对象
User 对象属性:username, password(必填项)password用哈希算法保存到数据库
is_staff : 用户是否拥有网站的管理权限.
is_active : 是否允许用户登录, 设置为``False``,可以不用删除用户来禁止 用户登录
is_authenticated()
如果是真正的 User 对象,返回值恒为 True 。 用于检查用户是否已经通过了认证。
通过认证并不意味着用户拥有任何权限,这个方法甚至也不检查该用户是否处于激活状态,只是表明用户成功的通过了认证。
这个方法很重要, 在后台用request.user.is_authenticated()判断用户是否已经登录,如果true则可以向前台展示request.user.name
创建用户
使用 create_user 辅助函数创建用户:
from django.contrib.auth.models import User #代表数据库中Django自带创建的auth_user这张表
user = User.objects.create_superuser(username='',password='') #这是创建超级用户的方法(备注:密码有限制)
user = User.objects.create_user(username='',password='',email='') #这个是创建普通用户的方法
check_password(passwd)
用户需要修改密码的时候,首先要让其输入原来的密码 ,如果给定的值通过了密码检查,返回 True
备注:用户修改密码时,肯定是已经登录的状态,所以,此时,校验密码时,我们可以取得用户输入的原密码,通过这个user_obj ,我们可以直接user_obj.check_password(原密码)来得到一个校验的结果True或False。然后根据这个状态我们在进行下一步的操作,即修改密码。在使用这个对象 .set_password(新密码=‘XX’),值得注意的时,修改完密码后,一定要保存 .save() 方法。
修改密码
使用 set_password() 来修改密码
user = User.objects.get(username='')
user.set_password(password='')
user.save()
字段的扩展
我们在使用Django自带的auth_user表时,他提供的字段是有限的,我们如果有其他的字段需求,就需要扩展这张表。
方式有两种:
一,使用ORM中OneToOne进行关联,创建一张表,关联这张auth_user 这张表。
#app下的models.py中 #导入这张Django内置的表
from django.contrib.auth.models import User class UserDetail(models.Model):
mobile = models.CharFiled(max_length=11)
user = models.OneToOneFiled(to=User) #切记,此处的User不需要加“”双引号,因为User是从其他文件中导入的,
这个User这是代指这张表。加引号的话,系统会从当前加载的整个py文件中反射的去找。显然找不到。
二,继承的方式 (推荐使用这种用法)
from django.contrib.auth.models import AbstractUser class UserInfo(AbstractUser):
mobile = models.CharFiled(max_length=11)
备注:使用继承的方式创建新表时,相当于我们对内置的auth_user表进行了覆盖,这是我们要在settings.py文件中指定一个参数:AUTH_USER_MODEL = "APP的名字.继承AbstractUser的类的类名" ,来告诉Django默认用户认证时使用哪张表。
使用继承的方式代替auth_user 表,我们任然可以使用所有的auth方法,创建用户时,变成 models.UserInfo.objects.create_user()这个用法了。
简单示例
def sign_up(request): state = None
if request.method == 'POST': password = request.POST.get('password', '')
repeat_password = request.POST.get('repeat_password', '')
email=request.POST.get('email', '')
username = request.POST.get('username', '')
if User.objects.filter(username=username):
state = 'user_exist'
else:
new_user = User.objects.create_user(username=username, password=password,email=email)
new_user.save() return redirect('/book/')
content = {
'state': state,
'user': None,
}
return render(request, 'sign_up.html', content)
注册示例代码
@login_required
def set_password(request):
user = request.user
state = None
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:
state = 'empty'
elif new_password != repeat_password:
state = 'repeat_error'
else:
user.set_password(new_password)
user.save()
return redirect("/log_in/")
else:
state = 'password_error'
content = {
'user': user,
'state': state,
}
return render(request, 'set_password.html', content)
修改密码示例