最近做项目的时候考虑过关于在django下用户模型的设计,包括注册和激活的逻辑,虽然最后没有采用这一台,而是选择了集成公司的AD,但还是写一篇笔记记录一下,以便以后回忆。
同步发表于个人站点:http://www.panzhixiang.cn
用户模型如下
from django.contrib.auth.models import AbstractUser
from django.db import models
class BaseModel(models.Model):
"""
模型抽象基类
"""
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
is_delete = models.BooleanField(default=False, verbose_name='删除标记')
class Meta:
# 说明这是一个抽象模型类
abstract = True
class User(AbstractUser, BaseModel):
"""
用户模型类
"""
class Meta:
db_table = 'user'
verbose_name = '用户'
verbose_name_plural = verbose_name
def __str__(self):
return self.username
用户激活流程(views.py中)如下:
from django.views.generic import View
from itsdangerous import TimedJSONWebSignatureSerializer as TJWSS
from itsdangerous import SignatureExpired
class RegisterView(View):
"""
注册类视图,get请求方法显示注册页面,post方法处理注册请求.
用户提交注册请求,后端接受请求以及数据后首先验证数据是否完整并符合要求;
在验证用户名是否已经存在,在我们设计的时候用户资料比较简单,只有用户名和邮箱,并且只能使用用户名登录,所以模型比较简单,实际在TOC或者TOB的时候一般都要兼容用户名、邮箱和手机号都能登录;
新用户创建后需要设置用户状态为“未激活”,在django的AbstractUser中也就是要给is_active属性赋值为False;
最后要给用户发送一封包含用户身份信息的激活邮件,这里使用用户ID作为唯一标志;
"""
def get(self, request):
return render(request, 'register.html')
def post(self, request):
username = request.POST.get('user_name')
pwd = request.POST.get('pwd')
cpwd = request.POST.get('pwd')
email = request.POST.get('email')
allow = request.POST.get('allow')
if not all([username, pwd, email]):
return render(request, 'register.html', {'errmsg': '信息填写不完整!'})
if allow != 'on':
return render(request, 'register.html', {'errmsg': '请勾选统一协议!'})
if not re.match(r'^[a-z0-9][\w.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
return render(request, 'register.html', {'errmsg': '邮箱格式不正确!'})
# 验证用户名是否已经存在
try:
user = User.objects.get(username=username)
except User.DoesNotExist as err:
user = None
else:
return render(request, 'register.html', {'errmsg': '该用户名已经存在!'})
try:
user = User.objects.create_user(username, email, pwd)
except Exception as err:
# 这里应该有一个错误捕捉和提醒机制
print(err)
return render(request, 'register.html', {'errmsg': '注册失败,请再次注册'})
else:
# 新建用户默认不激活,需要用户点击激活连接之后再设为激活状态
user.is_active = False
user.save()
# 初始化加密器,配置秘钥和超时时间
encrypter = TJWSS(SECRET_KEY, 3600)
encrypted_user_id = encrypter.dumps(user.id).decode('utf-8')
# 发送激活邮件,使用了celery,不作详细说明
send_active_email.delay([email,], encrypted_user_id)
return render(request, 'index.html')
class ActiveView(View):
"""
用户激活类视图
"""
def get(self, request, encrypted_user_id):
encrypter = TJWSS(SECRET_KEY, 3600)
try:
user_id = encrypter.loads(encrypted_user_id)
user = User.objects.get(id=user_id)
user.is_active = 1
user.save()
return redirect(reverse('user:login'))
except SignatureExpired as err:
return HttpResponse('激活链接已经过期')