Django基础之扩展内置用户模型
一:内置验证系统
1.1 auth模块
from django.contrib import auth
django.contrib.auth中提供了许多方法,这里主要介绍其中的三个
authenticate() :
提供了用户认证,即验证用户名以及密码是否正确,一般需要username password两个关键字参数
如果认证信息有效,会返回一个 User 对象。authenticate()会在User 对象上设置一个属性标识那种认证后端认证了该用户,且该信息在后面的登录过程中是需要的。当我们试图登陆一个从数据库中直接取出来不经过authenticate()的User对象会报错的!
user = authenticate(username='someone',password='somepassword')
注意:
在Django1.8版本中,authenticate方法传入username, password两个参数后是不校验is_active字段的
在Django2.0版本中,authenticate方法传入username, password两个参数后,如果is_active字段为False时,将返回None
如果想在Django2.0版本中校验 is_active 字段,可以settings配置文件中添加下面一行配置
AUTHENTICATION_BACKENDS = ['django.contrib.auth.backends.AllowAllUsersModelBackend']
login(HttpRequest, user):
该函数接受一个HttpRequest对象,以及一个认证了的User对象
此函数使用django的session框架给某个已认证的用户附加上session id等信息。
logout(request) 注销用户:
该函数接受一个HttpRequest对象,无返回值。当调用该函数时,当前请求的session信息会全部清除。该用户即使没有登录,使用该函数也不会报错。
1.2 User对象
如果是真正的 User 对象,返回值恒为 True 。 用于检查用户是否已经通过了认证。
通过认证并不意味着用户拥有任何权限,甚至也不检查该用户是否处于激活状态,这只是表明用户成功的通过了认证。 这个方法很重要, 在后台用request.user.is_authenticated判断用户是否已经登录,如果true则可以向前台展示request.user.username
login_required装饰器:
若用户没有登录,则会跳转到django默认的 登录URL '/accounts/login/ ’ (这个值可以在settings文件中通过LOGIN_URL进行修改)。并传递当前访问url的绝对路径 (登陆成功后,会重定向到该路径)。
create_user :
使用 create_user 辅助函数创建用户
from django.contrib.auth.models import User
def index(request):
user = User.objects.create_user(username = 'andy', email = '[email protected]', password = '123456')
# 在默认的auth_user表中创建用户,默认is_active = 1,激活的
return HttpResponse('index page')
create_superuser:
创建后台超级用户
user = User.objects.create_superuser(username = 'rambo', email = '[email protected]', password = '123456')
# 当然也可以在命令行中创建
check_password:
用户需要修改密码的时候 首先要让他输入原来的密码 ,如果给定的字符串通过了密码检查,返回 True
set_password:
使用 set_password() 来修改密码
user = User.objects.get(username='')
user.set_password(password='')
user.save
1.3 用户认证实例
from django.shortcuts import render, redirect
from django.contrib import auth
from django.contrib.auth.decorators import login_required
@login_required
def index(request):
return render(request, 'index.html')
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = auth.authenticate(username = username, password = password)
if user:
auth.login(request, user)
# path = request.GET.get('next', '/user/index/')
path = request.GET.get('next') or '/user/index/'
return redirect(path)
else:
return redirect('/user/login/')
return render(request, 'login.html')
def logout(request):
auth.logout(request)
return redirect('/user/login/')
二:扩展内置用户模型
2.1 Proxy模型扩展
如果只需要在原有的基础之上增加一些操作方法的话,使用该方法
class Person(User):
class Meta:
proxy = True
@classmethod
def get_blacklist(cls):
'''获取is_active=False的用户'''
return cls.objects.filter(is_active=False)
注意:
只能添加方法,不能添加属性(也就是不能添加自定义字段)
操作Person类实际上就是操作User类
2.2 一对一外键扩展
如果想要在原来模型的基础之上添加新的字段,那么可以使用一对一外键的方式
from django.dispatch import receiver
from django.db.models.signals import post_save
class UserExtension(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='extension')
telephone = models.CharField(max_length=11)
school = models.CharField(max_length=100)
@receiver(post_save, sender = User)
def handler_user_extension(sender, instance, created, **kwargs):
if created:
UserExtension.objects.create(user = instance)
else:
instance.extension.save()
使用该方式可以自定义验证系统
2.3 继承AbstractUser扩展
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager
from django.db import models
class UserManager(BaseUserManager):
def _create_user(self, mobile, username, password, **kwargs):
if not all([mobile, username, password]):
raise ValueError('mobile, username, password all required')
user = self.model(mobile = mobile, username = username, **kwargs)
user.set_password(password)
user.save()
return user
def create_user(self, mobile, username, password, **kwargs):
kwargs['is_superuser'] = False
return self._create_user(mobile, username, password, **kwargs)
def create_superuser(self, mobile, username, password, **kwargs):
kwargs['is_superuser'] = True
kwargs['is_staff'] = True
return self._create_user(mobile, username, password, **kwargs)
class User(AbstractUser):
telephone = models.CharField(max_length = 11, unique = True)
school = models.CharField(max_length = 100)
USERNAME_FIELD = 'telephone' # 告诉Django,在使用authenticate()方法做验证时使用telephone这个字段,user=authenticate(request,username=telephone,password=password)
objects = UserManager()
class Meta:
db_table = 'user'
Django默认的验证系统 authenticate() 方法需要传递 username, password二个字段,通过上面的UserManager方法对create_user方法,使用其支持传递自定义的三个字段:telephone, username, password
在调用 authenticate验证方法时默认传递的参数是 username = username, password = password,经过上面 USERNAME_FIELD = ‘telephone’,在传递参数时需要传递 username = telephone, password = password
创建完数据模型后,还必须通知django,要使用自定义的User模型类。在settings配置文件中添加下面一行代码:
AUTH_USER_MODEL = 'user.User' # APP_name.模型
2.4 继承AbstractBaseUser
如果想改变默认的验证方式,并且对于原User模型上的一些字段不想要,那么可以自定义一个模型,然后继承自AbstractBaseUser,再次添加你想要的字段。这种方式比较麻烦,最好是确定自己对Django比较了解才使用。
from django.contrib.auth.base_user import BaseUserManager, AbstractBaseUser
from django.contrib.auth.models import AbstractUser, PermissionsMixin
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length = 50)
email = models.EmailField(unique = True)
telephone = models.CharField(max_length=11, unique = True)
is_active = models.BooleanField(default = True)
USERNAME_FIELD = 'telephone'
REQUIRED_FIELDS = [] # 这里是创建createsuperuser时指定需要哪些字段,为空,说明需要上面的USERNAME_FIELD值与password字段
objects = UserManager()
def get_full_name(self):
return self.username
def get_short_name(self):
return self.username
settings配置文件中配置:
AUTH_USER_MODEL = 'book.User'
数据迁移后在数据中生成字段有:id, password, last_login, is_superuser, username , email, telephone, is_actiave
创建数据与验证数据:
def index(request):
telephone = '19976959220'
password = '123456'
username = 'ginvip'
# user = User.objects.create_user(telephone = telephone,password = password, username = username) # 创建数据
user = authenticate(request, username = telephone, password = password) # 数据验证
if user:
print(user)
print('验证成功')
else:
print('验证失败')
return HttpResponse('OK')
2.5 获取用户模型类
from django.contrib.auth import get_user_model # 会从settings配置文件中获取 AUTH_USER_MODEL值
user = get_user_model()