本功能实现用到了:模板继承,模板语言,ORM,auth和forms组件,总体来说,比较常规的功能,没有新的知识点。新了解的东西就是Django内置了发邮件的功能。
FBV(function base views) 就是在视图里使用函数处理请求。
CBV(class base views) 就是在视图里使用类处理请求。
这个项目使用的是CBV(比较好用)。
设置:
# 静态文件路径
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
一、登录
有两种登录方式:邮箱登录和用户名登录
1、用户名登录(CBV)
后台获取用户提交的用户名和密码,用form组件进行格式校验,再用auth组件校验用户信息,成功则返回首页,失败返回登录页面。
url:
url(r'^login/$', LoginView.as_view(), name='login'),#name可以用于反向查找,即url变化时,代码中不需改动
视图函数:
class LoginView(View):
def get(self, request):
return render(request, 'login.html')
def post(self, request):
login_form = LoginForm(request.POST) # 使用forms组件进行格式校验
if login_form.is_valid(): # 如果合法
username = request.POST.get('username')
password = request.POST.get('password')
user = auth.authenticate(username=username, password=password)
# 使用auth组件进行校验用户信息
if user is not None:
if user.is_active:
auth.login(request, user) # 注册用户后才能使用
return redirect(reverse('index'))
else:
return render(request, "login.html", {"msg": "用户未激活!"})
else:
return render(request, 'login.html', {'msg': '用户名或密码错误'})
else:
return render(request, 'login.html', {'login_form': login_form})
2、邮箱登录
class CustomBackend(ModelBackend):# 设置邮箱和用户名都可以登录,重载authenticate方法
def authenticate(self, request, username=None, password=None, **kwargs):
try:
user = UserProfile.objects.get(Q(username=username) | Q(email=username)) # 或
# 密码为密文
# AbstractUser中有check_password方法
if user.check_password(password):
return user
except Exception as e:
return None
二、注册
url:
url(r'^register/$', RegisterView.as_view(), name='register'),
url(r'^captcha/', include('captcha.urls')), # 验证码
url(r'^active/(?P<active_code>.*)/$', ActiveUserView.as_view(), name="user_active"), # 用户激活,active_code是传递的参数
步骤:1、同样需要使用forms组件
# 自定义注册
class RegisterForm(forms.Form):
email = forms.CharField(required=True)
password = forms.CharField(required=True, max_length=6)
captcha = CaptchaField(error_messages={
'invalid': '验证码错误'
})
2、后台获取用户提交的信息,首先检查这个用户是否注册过(也可以在前端页面注册时,发送ajax请求进行检查),检查通过,则在数据库中创建用户
class RegisterView(View):
def get(self, request):
register_form = RegisterForm()
return render(request, 'register.html', locals())
def post(self, request):
register_form = RegisterForm(request.POST)
if register_form.is_valid():
# 校验通过
email = request.POST.get('email')
pwd = request.POST.get('password')
# 检查这个用户名是否已经注册过
flag = UserProfile.objects.filter(email=email)
if flag:
return render(request, 'register.html', {'register_form': register_form, 'msg': '用户已经注册'})
# 密码加密
pwd = make_password(pwd)
# 创建新用户
# print(email, pwd)
UserProfile.objects.create(username=email, email=email, is_active=False, password=pwd)
# 发送注册邮件
email_body, email_title, email_url = send_register_email(email, 'register')
# return redirect(reverse('login'))
a = mark_safe("{0}<a href='{1}'>{2}</a>".format(email_body, email_url, email_url))
return render(request, 'active.html', locals())
return render(request, "register.html", {"register_form": register_form})
3、创建用户之后,用户的状态是未激活,原教程是发送邮件进行激活,我使用邮件激活,没有成功,所以我是新建一个页面,页面中有一个激活链接,点击后,用户状态激活。
# 获取随机字符串
def get_random(length=8):
random = str(uuid.uuid1())
code = random[0:length]
return code
def send_register_email(email, send_type='register'):
email_record = EmailVerifyRecord()
if send_type == 'update_email':
code = get_random(4)
code = code.replace('-', '') # 去除横杠
else:
code = get_random(16)
code = code.replace('-', '')
email_record.code = code
email_record.email = email
email_record.send_type = send_type
email_record.save()
email_title = ""
email_body = ""
if send_type == 'register':
email_title = "icourse注册激活"
email_body = "请点击下面的链接激活你的账号"
email_url = "http://127.0.0.1:8000/active/{0}".format(code) # 忘写端口了,我套
# send_status = send_mail(email_title, email_body, EMAIL_FROM, [email]) # 邮件发送不成功,自己写个页面,进行验证
# if send_status:
# pass
return email_body, email_title, email_url
三、忘记密码
url:
url(r'^forget/$', ForgetView.as_view(), name='forget_pwd'),
url(r'^reset/(?P<active_code>.*)/$', ResetView.as_view(), name='reset_pwd'), # 重置密码链接
url(r'^modify_pwd/$', ModifyPwdView.as_view(), name="modify_pwd"), # 修改密码链接
1、用户点击忘记密码,转到找回密码页面,用户提交信息,用forms组件进行格式校验,
# 忘记密码
class ForgetForm(forms.Form):
email = forms.CharField(required=True)
captcha = CaptchaField(error_messages={'invalid': '验证码错误'})
2、格式校验通过,向后台发送post请求,获取用户数据
# 找回密码
class ForgetView(View):
def get(self, request):
forget_form = ForgetForm()
print('in get')
return render(request, 'forgetpwd.html', locals())
def post(self, request):
forget_form = ForgetForm(request.POST)
print('in post')
if forget_form.is_valid():
email = request.POST.get('email')
email_body, email_title, email_url = send_register_email(email, 'forget')
# 生成链接
a = mark_safe("{0}<a href='{1}'>{2}</a>".format(email_body, email_url, email_url))
return render(request, 'reset_link.html', locals())
return render(request, 'forgetpwd.html', locals()) # 提交数据的格式不正确,重新提交
3、发起一个重置密码请求,进入重置密码页面,用户点击链接,返回修改密码页面
class ResetView(View):
# 点击重置密码链接,进入此逻辑,返回重置密码页面
def get(self, request, active_code):
obj = EmailVerifyRecord.objects.filter(code=active_code).first() # 找到有没有重置密码的对象
if obj:
email=obj.email
return render(request, 'password_reset.html', locals()) # 返回重置密码页面
else:
return render(request, 'register.html')
4、修改密码
# 修改密码
class ModifyPwdView(View):
def post(self, request):
modify_form = ModifyPwdForm(request.POST)
if modify_form.is_valid():
pwd1 = request.POST.get('password1')
pwd2 = request.POST.get('password2')
email = request.POST.get('email')
if pwd1 != pwd2:
return render(request, 'password_reset.html', {'email': email, 'msg': '密码不一致'})
user_obj = UserProfile.objects.filter(email=email).first()
user_obj.password = make_password(pwd1)
user_obj.save()
return render(request, 'login.html')
else:
email = request.POST.get('email')
return render(request,'password_reset.html',locals())
四、退出登录
class LogoutView(View):
def get(self, request):
auth.logout(request)
return redirect(reverse('index'))