七、增加邮箱验证
1、为用户表增加字段
我们的用户表继承改写django认证系统的用户表,里面有is_active字段,但是这个字段默认是激活状态,所以为了方便,我们给用户表添加一个新的字段,标志用户是否激活。
给UserProfile模型类添加字段
is_start = models.BooleanField(default=False, verbose_name='是否激活')
from django.db import models from django.contrib.auth.models import AbstractUser from datetime import datetime # Create your models here. class UserProfile(AbstractUser): image = models.ImageField(upload_to='user/', max_length=200, verbose_name='用户头像', null=True, blank=True) nick_name = models.CharField(max_length=20, verbose_name='用户昵称', null=True, blank=True) birthday = models.DateTimeField(verbose_name='用户生日', null=True, blank=True) gender = models.CharField(choices=(('girl', '女'), ('boy', '男')), max_length=10, verbose_name='用户性别', default='girl') address = models.CharField(max_length=200, verbose_name='用户地址', null=True, blank=True) phone = models.CharField(max_length=11, verbose_name='用户手机', null=True, blank=True) # 这个字段控制激活 is_start = models.BooleanField(default=False, verbose_name='是否激活') add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间') def __str__(self): return self.username class Meta: verbose_name = '用户信息' verbose_name_plural = verbose_name class BannerInfo(models.Model): image = models.ImageField(upload_to='banner/', verbose_name='轮播图片', max_length=200) url = models.URLField(default='http://www.atguigu.com', max_length=200, verbose_name='图片链接') add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间') def __str__(self): return str(self.image) class Meta: verbose_name = '轮播图信息' verbose_name_plural = verbose_name class EmailVerifyCode(models.Model): code = models.CharField(max_length=20, verbose_name='邮箱验证码') email = models.EmailField(max_length=200, verbose_name='验证码邮箱') send_type = models.IntegerField(choices=((1, 'register'), (2, 'forget'), (3, 'change')), verbose_name='验证码类型') add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间') def __str__(self): return str(self.code) class Meta: verbose_name = '邮箱验证码' verbose_name_plural = verbose_nameuser/models.py完整代码
2、配置settings文件
(1)、准备工作
自备163网易邮箱,登录设置,开启POP3/SMTP/IMAP服务,复制smtp服务器地址,并设置客户端授权密码
(2)、配置settings
EMAIL_HOST = 'smtp.yeah.net' EMAIL_PORT = 25 EMAIL_HOST_USER = 'huiyichanmian@yeah.net' # 你的邮箱 EMAIL_HOST_PASSWORD = '123456' # 你的客户端密码 EAMIL_FROM = 'huiyichanmian@yeah.net' # 你的邮箱
3、定义发邮件的工具函数
在根目录下创建utils包,在utils包下创建send_mail_tool.py文件
(1)、创建验证码
# from random import choice from random import randrange def get_random_code(code_length): code = '' code_source = '12345666666789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM' # 码源 # for i in range(code_length): # # 随机选择一个字符 # code += choice(code_source) for i in range(code_length): string = code_source[randrange(0, len(code_source)-1)] code += string return code
(2)、发送邮件
from users.models import EmailVerifyCode from django.core.mail import send_mail from GuLiEdu.settings import EAMIL_FROM def send_email_code(email, send_type): # 第一步:创建邮箱验证码对象,保存数据库,用来以后做对比 code = get_random_code(6) a = EmailVerifyCode() a.email = email a.send_type = send_type a.code = code a.save() # 第二步:正式的发邮件功能 if send_type == 1: send_title = '欢迎注册谷粒教育网站' send_body = '请点击一下链接激活您的账号:\n' \ 'http://127.0.0.1:8000/users/user_active/' + code send_mail(send_title, send_body, EAMIL_FROM, [email])
4、配置子路由
from django.urls import path, re_path from users.views import register, user_logout, user_login, user_active app_name = 'users' urlpatterns = [ path('register/', register, name='register'), path('login/', user_login, name='login'), path('logout/', user_logout, name='logout'), re_path(r'user_active/(\w+)/$', user_active, name='user_active') ]
5、编写视图函数
(1)、修改注册接口(加入发送邮件的功能)
def register(request): if request.method == 'GET': # 这里实例化form类,目的不是为了验证,而是为了使用验证码 user_register_form = UserRegisterForm() return render(request, 'register.html', { 'user_register_form': user_register_form }) else: user_register_form = UserRegisterForm(request.POST) # 验证表单 if user_register_form.is_valid(): # 判断是否合法 email = user_register_form.cleaned_data['email'] password = user_register_form.cleaned_data['password'] user_list = UserProfile.objects.filter(Q(username=email) | Q(email=email)) if user_list: return render(request, 'register.html', { 'msg': '用户已经存在' }) else: a = UserProfile() a.username = email # 用户名存库 a.set_password(password) # 密码存库,经过处理 a.email = email a.save() # 保存 # 发送激活邮件邮件 send_email_code(email, 1) return HttpResponse('请尽快前往您的邮箱激活,否则无法登录') # return redirect(reverse('index')) else: return render(request, 'register.html', { 'user_register_form': user_register_form })
(2)、修改登录接口(验证是否激活)
def user_login(request): if request.method == 'GET': return render(request, 'login.html') else: user_login_form = UserLoginForm(request.POST) if user_login_form.is_valid(): # 判断是否合法 email = user_login_form.cleaned_data['email'] password = user_login_form.cleaned_data['password'] user = authenticate(username=email, password=password) # 验证邮箱密码 if user: if user.is_start: # 判断是否激活 login(request, user) # 登录 return redirect(reverse('index')) else: return HttpResponse('请去您的邮箱激活,否则无法登录') else: return render(request, 'login.html', { 'msg': '邮箱或密码有误' }) else: return render(request, 'login.html', { 'user_login_form': user_login_form })
(3)、激活试图函数
def user_active(request, code): if code: # 获取到邮件中的code email_ver_list = EmailVerifyCode.objects.filter(code=code) # 在邮箱验证码表中查找code,获取到邮箱对象列表 if email_ver_list: email_ver = email_ver_list[0] # 获取邮箱对象 email = email_ver.email # 获取邮箱 user_list = UserProfile.objects.filter(username=email) # 获取用户对象列表 if user_list: user = user_list[0] # 获取用户对象 user.is_start = True # 更改用户激活状态 user.save() # 保存 return redirect(reverse('users:login')) else: pass else: pass else: pass