Django默认用户模型类
django.contrib.auth.models
class AbstractUser(AbstractBaseUser, PermissionsMixin):
"""
An abstract base class implementing a fully featured User model with
admin-compliant permissions.
Username and password are required. Other fields are optional.
"""
username_validator = UnicodeUsernameValidator() if six.PY3 else ASCIIUsernameValidator()
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=30, 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 = UserManager()
EMAIL_FIELD = 'email'
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
abstract = True
def clean(self):
super(AbstractUser, self).clean()
self.email = self.__class__.objects.normalize_email(self.email)
def get_full_name(self):
"""
Returns the first_name plus the last_name, with a space in between.
"""
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
"Returns the short name for the user."
return self.first_name
def email_user(self, subject, message, from_email=None, **kwargs):
"""
Sends an email to this User.
"""
send_mail(subject, message, from_email, [self.email], **kwargs)
class User(AbstractUser):
"""
Users within the Django authentication system are represented by this
model.
Username, password and email are required. Other fields are optional.
"""
class Meta(AbstractUser.Meta):
swappable = 'AUTH_USER_MODEL'
User对象是认证系统的核心,父类为AbstractUser类。
假设前端POST请求传来如下参数:
username = request.POST.get('username')
password = request.POST.get('password')
password2 = request.POST.get('password2')
mobile = request.POST.get('mobile')
allow = request.POST.get('allow')
后端视图views.py将首先检验所传数据的合法性,然后调用create_user方法向数据库新增用户记录。
class RegisterView(View):
"""用户注册"""
def get(self, request):
"""提供用户注册页面
"""
return render(request, 'register.html')
def post(self, request):
"""实现用户注册业务逻辑"""
# 接收参数
username = request.POST.get('username')
password = request.POST.get('password')
password2 = request.POST.get('password2')
mobile = request.POST.get('mobile')
allow = request.POST.get('allow')
# 校验参数: 前后端的校验需要分开,避免恶意用户越过前端逻辑发送请求,要保证后端安全,前后端的校验逻辑相同
# 判断参数是否齐全
# all([列表]):会去校验列表中的元素是否为空,只要有一个为空,返回false
if not all([username, password, password2, mobile, allow]):
# return '如果缺少必传参数,响应错误提示信息,403'
return http.HttpResponseForbidden('缺少必传参数')
# 判断用户名是否是5-20个字符
if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
return http.HttpResponseForbidden('请输入5-20个字符的用户名')
# 判断密码是否是8-20个字符
if not re.match(r'^[a-zA-Z0-9]{8,20}$', password):
return http.HttpResponseForbidden('请输入8-20位的密码')
# 判断两次输入的密码是否一致
if password != password2:
return http.HttpResponseForbidden('两次输入的密码不一致')
# 判断手机号是否合法
if not re.match(r'^1[3-9]\d{9}$', mobile):
return http.HttpResponseForbidden('请输入正确的手机号码')
# 判断是否勾选用户协议
if allow != 'on':
return http.HttpResponseForbidden('请勾选用户协议')
# 保存注册数据:是注册业务的核心
try:
user = User.objects.create_user(username=username, password=password, mobile=mobile)
except DatabaseError:
return render(request, 'register.html', {'register_errmsg': '注册失败'})
# 响应结果:重定向到首页
return http.HttpResponse('注册成功,重定向到首页')
流程分析:
(1) 前端传来数据,后端视图检查数据的合法性。
在username = request.POST.get('username') 和 user = User.objects.create_user(username=username, password=password, mobile=mobile) 处分别打断点。
(2) 使用Step Over键,观察数据合法性被逐步验证的过程,直至调用创建用户的方法
user = User.objects.create_user(username=username, password=password, mobile=mobile)
点击Step Into My Code键。
这样就来到了django.contrib.auth.models模块:
分别打上如下三个断点:
(3) 使用Step Over键直到调用_create_user方法
return self._create_user(username, email, password, **extra_fields)
可以观察到:
username, email(None), password, extra_fields(mobie, is_staff, is_superuser)字段的值。
接下来使用Step Into My Code键:
当执行完
user = self.model(username=username, email=email, **extra_fields)
后,可发现生成了user对象:
当执行完
user.set_password(password)
后,可发现user对象多了password属性,属性值为加密后的password。
而后执行完
user.save(using=self._db)
之后,就向数据库新增了一条用户记录。