django自定义user_3d模型下载源码前言Django为我们提供了内置的User模型,不需要我们再额外定义用户模型,建立用户体系了。它的完整的路径是在django.contr
前言 Django
为我们提供了内置的User
模型,不需要我们再额外定义用户模型,建立用户体系了。它的完整的路径是在django.contrib.auth.models.User
。
User模型源码分析 class User(AbstractUser): """ Django 身份验证系统中的用户由该模型表示 需要用户名和密码。其他字段是可选的。 """ class Meta(AbstractUser.Meta): swappable = 'AUTH_USER_MODEL'
我们可以看到User
这个类本身没干什么事情,而是继承自AbstractUser
类,那么我们查看下AbstractUser
的源码
class AbstractUser(AbstractBaseUser, PermissionsMixin): """ 一个抽象基类实现了一个功能齐全的用户模型 符合管理员的权限。 需要用户名和密码。 其他字段是可选的。 """ # 用户民校验 username_validator = UnicodeUsernameValidator() username = models.CharField( _('username'), max_length=150, unique=True, help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'), validators=[username_validator], error_messages={ 'unique': _("A user with that username already exists."), }, ) first_name = models.CharField(_('first name'), max_length=30, blank=True) last_name = models.CharField(_('last name'), max_length=150, blank=True) email = models.EmailField(_('email address'), blank=True) is_staff = models.BooleanField( _('staff status'), default=False, help_text=_('Designates whether the user can log into this admin site.'), ) is_active = models.BooleanField( _('active'), default=True, help_text=_( 'Designates whether this user should be treated as active. ' 'Unselect this instead of deleting accounts.' ), ) date_joined = models.DateTimeField(_('date joined'), default=timezone.now) # objects用户管理,里面有创建用户的方法 objects = UserManager() EMAIL_FIELD = 'email' # 用来描述User模型名字字段的字符串,作为唯一的标识。如果没有修改,那么会使用USERNAME来作为唯一字段。 USERNAME_FIELD = 'username' # 一个字段名列表,用于当通过createsuperuser管理命令创建一个用户时的提示。 REQUIRED_FIELDS = ['email'] class Meta: verbose_name = _('user') verbose_name_plural = _('users') abstract = True def clean(self): super().clean() self.email = self.__class__.objects.normalize_email(self.email) def get_full_name(self): """ 返回first_name和last_name,中间有个空格 """ full_name = '%s %s' % (self.first_name, self.last_name) return full_name.strip() def get_short_name(self): """返回用户的first_name.""" return self.first_name def email_user(self, subject, message, from_email=None, **kwargs): """发送邮件给用户.""" send_mail(subject, message, from_email, [self.email], **kwargs)
我们可以看到AbstractUser
继承自AbstractBaseUser
和PermissionsMixin
AbstractBaseUser
:基础的User模型类PermissionsMixin
:权限类我们先看看AbstractUser
有哪些字段和方法
字段 username
:用户名。150个字符以内。可以包含数字和英文字符,以及_
、@
、+
、.
和-
字符。不能为空,且必须唯一!first_name
:外国人的first_name
,在30个字符以内。可以为空。last_name
:外国人的last_name
,在150个字符以内。可以为空。email
:邮箱。可以为空。password
:密码。经过哈希过后的密码。(父类AbstractBaseUser
的属性)groups
:分组。一个用户可以属于多个分组,一个分组可以拥有多个用户。groups
这个字段是跟Group
的一个多对多的关系。(父类PermissionsMixin
的属性)user_permissions
:权限。一个用户可以拥有多个权限,一个权限可以被多个用户所有用。和Permission
属于一种多对多的关系。(父类PermissionsMixin
的属性)is_staff
:是否可以进入到admin
的站点。代表是否是员工is_active
:是否是可用的。对于一些想要删除账号的数据,我们设置这个值为False
就可以了,而不是真正的从数据库中删除。is_superuser
:是否是超级管理员。如果是超级管理员,那么拥有整个网站的所有权限。(父类PermissionsMixin
的属性)last_login
:上次登录的时间。(父类AbstractBaseUser
的属性)date_joined
:账号创建的时间。 User模型基本用法
创建用户 创建用户需要用到objects = UserManager()
中的方法,我们点击UserManager
查看源码
class UserManager(BaseUserManager): use_in_migratiOns= True def _create_user(self, username, email, password, **extra_fields): """ 使用给定的用户名、电子邮件和密码创建并保存用户。 """ # 如果没有username则抛出异常 if not username: raise ValueError('The given username must be set') # 标准化电子邮件,查看源码会发现是用@进行分割 email = self.normalize_email(email) # 标准化用户名 username = self.model.normalize_username(username) user = self.model(username=username, email=email, **extra_fields) # 为用户设置密码,将纯文本密码转换为用于数据库存储的哈希值 user.set_password(password) # 保存用户 user.save(using=self._db) return user def create_user(self, username, email=None, password=None, **extra_fields): # 设置is_staff默认值为False,is_superuser默认值为False extra_fields.setdefault('is_staff', False) extra_fields.setdefault('is_superuser', False) return self._create_user(username, email, password, **extra_fields) def create_superuser(self, username, email, password, **extra_fields): # 设置is_staff默认值为True,is_superuser默认值为True extra_fields.setdefault('is_staff', True) extra_fields.setdefault('is_superuser', True) # 如果调用此方法,is_staff必须为True,否则会抛出异常 if extra_fields.get('is_staff') is not True: raise ValueError('Superuser must have is_staff=True.') # 如果调用此方法,is_superuser必须为True,否则会抛出异常 if extra_fields.get('is_superuser') is not True: raise ValueError('Superuser must have is_superuser=True.') return self._create_user(username, email, password, **extra_fields)
以上源码写的十分清楚相信小伙伴们也看得很清晰了,接下里我们实际操作一下
def index(request): user = User.objects.create_user(username="jkc", email="123@qq.com", password="123456") user.save() return HttpResponse("ok")
我们访问以上视图后,就创建了一个普通用户,查看数据库中的auth_user
表,如下
创建超级用户 创建超级用户有两种方式。第一种是使用代码的方式。用代码创建超级用户跟创建普通用户非常的类似,只不过是使用create_superuser
。示例代码如下:
def index(request): user = User.objects.create_superuser(username="jkc3", email="123@qq.com", password="123456") user.save() return HttpResponse("ok")
也可以通过命令行的方式。命令如下:
python manage.py createsuperuser
后面就会提示你输入用户名、邮箱以及密码。
修改密码 因为密码是需要经过加密后才能存储进去的。所以如果想要修改密码,不能直接修改password
字段,而需要通过调用set_password
来达到修改密码的目的。示例代码如下:
def index(request): user = User.objects.get(pk=1) user.set_password('111111') user.save() return HttpResponse("ok")
改之前密码为$1FMDwi2zsgQu$2+8/zL6ZR43oXIvIRGfK6xrWUnv2IRjdPxVaqEwqyjM=
,改完之后为$u6rNdNTvLbEG$r4TcrVsTsibcVF3ZfZIJPjLNvq73wyusLShDmpSZeKM=
登录验证 Django
的验证系统已经帮我们实现了登录验证的功能。通过django.contrib.auth.authenticate
即可实现。这个方法只能通过username
和password
来进行验证。示例代码如下:
def index(request): user = authenticate(username="jkc", password="111111") if user: return HttpResponse("登录成功") else: return HttpResponse("登录失败")
扩展用户模型 Django
内置的User
模型虽然已经足够强大了。但是有时候还是不能满足我们的需求。比如在验证用户登录的时候,他用的是用户名
作为验证,而我们有时候需要通过手机号
码或者邮箱
来进行验证。还有比如我们想要增加一些新的字段。那么这时候我们就需要扩展用户模型了。扩展用户模型有多种方式。这里我们来一一讨论下。
继承自AbstractUser 对于authenticate
不满意,并且不想要修改原来User
对象上的一些字段,但是想要增加一些字段,那么这时候可以直接继承自django.contrib.auth.models.AbstractUser
,其实这个类也是django.contrib.auth.models.User
的父类。比如我们想要在原来User
模型的基础之上添加一个phone
字段。示例代码如下:
from django.contrib.auth.base_user import BaseUserManager from django.db import models from django.contrib.auth.models import AbstractUser class UserManager(BaseUserManager): use_in_migratiOns= True def _create_user(self,phone,password,**extra_fields): if not phone: raise ValueError("请填入手机号码!") if not password: raise ValueError('请输入密码!') user = self.model(phOne=phone,*extra_fields) user.set_password(password) user.save() return user def create_user(self,phone,password,**extra_fields): extra_fields.setdefault('is_superuser',False) return self._create_user(phone,password) def create_superuser(self,phone,password,**extra_fields): extra_fields['is_superuser'] = True return self._create_user(phone,password) class User(AbstractUser): phOne= models.CharField(max_length=11, unique=True, verbose_name="手机号码") # 指定phone作为USERNAME_FIELD,以后使用authenticate # 函数验证的时候,就可以根据phone来验证,而不是原来的username USERNAME_FIELD = 'phone' # 提醒用户输入的字段 REQUIRED_FIELDS = [] # 重新定义Manager对象,在创建user的时候使用phone和password,而不是使用username和password objects = UserManager()
然后再在settings中配置好AUTH_USER_MODEL=yourapp.User
。 注意:这种方式因为破坏了原来User
模型的表结构,所以必须要在第一次migrate
前就先定义好。 以上我们重新定义了User
模型,新增了phone
字段,并把phone
作为校验字段,我们先来看下数据库的表结构 接下里我们通过createsuperuser
命令来创建超级用户 我们会发现创建超级用户的时候,不再需要username
字段来校验了,接下来我们验证一下登录,现在的结构需要用phone
字段和密码来登录,而不是使用username
,我们编写视图函数来尝试
def index(request): # 先使用手机号密码登录 user = authenticate(username="12345678901", password="admin123") if user: return HttpResponse('手机号密码登录成功') else: return HttpResponse('手机号密码登录失败')
然后访问视图,返回手机号密码登录成功
,说明现在校验的字段的内容是手机号,我们再来试试使用用户名能否登录成功
def index(request): # 由于之前未设置username,这里先为id为1的用户设置username user = User.objects.get(pk=1) user.username = "jkc" user.save() print("保存成功") u = authenticate(username="jkc", password="admin123") if u: return HttpResponse('用户名登录成功') else: return HttpResponse('用户名登录失败')
我们访问视图,最后返回的是手机号验证码登录失败
,说明现在username
校验的是手机号,我们输入用户名是校验不通过的