• 在线教育平台,邮件激活(9)


    在Python中已经内置了一个smtp邮件发送模块,Django在此基础上进行了简单地封装,让我们在Django环境中可以更方便更灵活的发送邮件。

    所有的功能都在django.core.mail中。

    首先settings里面设置

    复制代码
    # settings.py
    
    EMAIL_HOST = "smtp.qq.com"  # SMTP服务器主机,默认qq邮箱是不开启的,需要用户自行开启
    EMAIL_PORT = 25             # 端口
    EMAIL_HOST_USER = "19@qq.com"       # 邮箱地址
    EMAIL_HOST_PASSWORD = "dwjybikexxxxxxxx"    # 密码
    EMAIL_USE_TLS= True
    EMAIL_FROM = "1184405959@qq.com"            # 邮箱地址

    在apps目录新建package utils,然后新建一个email_send.py文件

    # apps/utils/email_send.py
    
    from random import Random
    from django.core.mail import send_mail
    
    from users.models import EmailVerifyRecord
    from MxOnline.settings import EMAIL_FROM
    
    # 生成随机字符串
    def random_str(random_length=8):
        str = ''
        # 生成字符串的可选字符串
        chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
        length = len(chars) - 1
        random = Random()
        for i in range(random_length):
            str += chars[random.randint(0, length)]
        return str
    
    # 发送注册邮件
    def send_register_eamil(email, send_type="register"):
        # 发送之前先保存到数据库,到时候查询链接是否存在
        # 实例化一个EmailVerifyRecord对象
        email_record = EmailVerifyRecord()
        # 生成随机的code放入链接
        code = random_str(16)
        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 = "NBA注册激活链接"
            email_body = "请点击下面的链接激活你的账号: http://127.0.0.1:8000/active/{0}".format(code)
    
            # 使用Django内置函数完成邮件发送。四个参数:主题,邮件内容,发件人邮箱地址,收件人(是一个字符串列表)
            send_status = send_mail(email_title, email_body, EMAIL_FROM, [email])
            # 如果发送成功
            if send_status:
                pass

    用户的激活:

    根据邮箱找到对应的用户,然后设置is_active = True来实现

    复制代码
    # 激活用户
    class ActiveUserView(View):
        def get(self, request, active_code):
            # 查询邮箱验证记录是否存在
            all_record = EmailVerifyRecord.objects.filter(code = active_code)
    
            if all_record:
                for record in all_record:
                    # 获取到对应的邮箱
                    email = record.email
                    # 查找到邮箱对应的user
                    user = UserProfile.objects.get(email=email)
                    user.is_active = True
                    user.save()
             # 验证码不对的时候跳转到激活失败页面
            else:
                return render(request,'active_fail.html')
            # 激活成功跳转到登录页面
            return render(request, "login.html", )

    在templates目录下创建 active_fail.html,代码如下:

    复制代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <p style="color: red;">链接失效</p>
    </body>
    </html>

    修改login视图

    添加一个判断,用户注册的后,等激活才能登陆

    # users/views.py
    
    from django.shortcuts import render
    from django.contrib.auth import authenticate,login
    
    from django.contrib.auth.backends import ModelBackend
    from .models import UserProfile,EmailVerifyRecord
    from django.db.models import Q
    from django.views.generic.base import View
    from .forms import LoginForm,RegisterForm
    from django.contrib.auth.hashers import make_password
    from utils.email_send import send_register_eamil
    
    #邮箱和用户名都可以登录
    # 基础ModelBackend类,因为它有authenticate方法
    class CustomBackend(ModelBackend):
        def authenticate(self, request, username=None, password=None, **kwargs):
            try:
                # 不希望用户存在两个,get只能有一个。两个是get失败的一种原因 Q为使用并集查询
                user = UserProfile.objects.get(Q(username=username)|Q(email=username))
    
                # django的后台中密码加密:所以不能password==password
                # UserProfile继承的AbstractUser中有def check_password(self, raw_password):
                if user.check_password(password):
                    return user
            except Exception as e:
                return None
    
    
    class LoginView(View):
        '''用户登录'''
    
        def get(self,request):
            return render(request, 'login.html')
    
        def post(self,request):
            # 实例化
            login_form = LoginForm(request.POST)
            if login_form.is_valid():
                # 获取用户提交的用户名和密码
                user_name = request.POST.get('username', None)
                pass_word = request.POST.get('password', None)
                # 成功返回user对象,失败None
                user = authenticate(username=user_name, password=pass_word)
                # 如果不是null说明验证成功
                if user is not None:
                    if user.is_active:
                        # 只有注册激活才能登录
                        login(request, user)
                        return render(request, 'index.html')
                    else:
                        return render(request, 'login.html', {'msg': '用户名或密码错误', 'login_form': login_form})
                # 只有当用户名或密码不存在时,才返回错误信息到前端
                else:
                    return render(request, 'login.html', {'msg': '用户名或密码错误','login_form':login_form})
    
            # form.is_valid()已经判断不合法了,所以这里不需要再返回错误信息到前端了
            else:
                return render(request,'login.html',{'login_form':login_form})
    
    
    # 激活用户的view
    class ActiveUserView(View):
        def get(self, request, active_code):
            # 查询邮箱验证记录是否存在
            all_record = EmailVerifyRecord.objects.filter(code = active_code)
    
            if all_record:
                for record in all_record:
                    # 获取到对应的邮箱
                    email = record.email
                    # 查找到邮箱对应的user
                    user = UserProfile.objects.get(email=email)
                    user.is_active = True
                    user.save()
                    # 激活成功跳转到登录页面
                    return render(request, "login.html", )
            # 自己瞎输的验证码
            else:
                return render(request, "register.html", {"msg": "您的激活链接无效"})
    
    
    class RegisterView(View):
        '''用户注册'''
        def get(self,request):
            register_form = RegisterForm()
            return render(request,'register.html',{'register_form':register_form})
    
        def post(self,request):
            register_form = RegisterForm(request.POST)
            if register_form.is_valid():
    
                user_name = request.POST.get('email', None)
                pass_word = request.POST.get('password', None)
    
                # 实例化一个user_profile对象
                user_profile = UserProfile()
                user_profile.username = user_name
                user_profile.email = user_name
                user_profile.is_active = False
                # 对保存到数据库的密码加密
                user_profile.password = make_password(pass_word)
                user_profile.save()
                send_register_eamil(user_name,'register')
                return render(request,'login.html')
            else:
                return render(request,'register.html',{'register_form':register_form})
    
    views.py
    users/views
    <form id="email_register_form" method="post" action="{% url 'register' %}" autocomplete="off">
                            <input type='hidden' name='csrfmiddlewaretoken' value='gTZljXgnpvxn0fKZ1XkWrM1PrCGSjiCZ' />
                            <div class="form-group marb20 {% if login_form.errors.email %}errorput{% endif %}">
                                <label>邮&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;箱</label>
                                <input  type="text" id="id_email" name="email" value="{{ register_form.email.value }}" placeholder="请输入您的邮箱地址" />
                            </div>
                            <div class="form-group marb8 {% if login_form.errors.password %}errorput{% endif %}">
                                <label>密&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;码</label>
                                <input type="password" id="id_password" name="password"  value="{{ register_form.password.value }}" placeholder="请输入6-20位非中文字符密码" />
                            </div>
                            <div class="form-group marb8 captcha1 {% if login_form.errors.captchal %}errorput{% endif %}">
                                <label>验&nbsp;证&nbsp;码</label>
                                {{ register_form.captcha }}
                            </div>
                            <div class="error btns" id="jsEmailTips">
                                {% for key,error in register_form.errors.items %}
                                    {{ error }}
                                {% endfor %}
                                {{ msg }}
                            </div>
                            <div class="auto-box marb8">
                            </div>
                            <input class="btn btn-green" id="jsEmailRegBtn" type="submit" value="注册并登录" />
                        <input type='hidden' name='csrfmiddlewaretoken' value='5I2SlleZJOMUX9QbwYLUIAOshdrdpRcy' />
                        {% csrf_token %}
                        </form>
    register.html

    添加邮件激活的url

    复制代码
    # MxOnline/urls.py
    
    import xadmin
    
    from django.urls import path,include,re_path
    
    from django.views.generic import TemplateView
    from users.views import LoginView,RegisterView,ActiveUserView
    
    
    urlpatterns = [
        path('xadmin/', xadmin.site.urls),
        path('', TemplateView.as_view(template_name='index.html'),name='index'),
        path('login/',LoginView.as_view(),name = 'login'),
        path('register/',RegisterView.as_view(),name = 'register'),
        path('captcha/',include('captcha.urls')),
        re_path('active/(?P<active_code>.*)/',ActiveUserView.as_view(),name='user_active'),
    ]
  • 相关阅读:
    从编程到入侵
    编程实现盗2005 Beta2版QQ
    Justin Frankel:Winamp的反斗奇星
    用安静的热情征服联合国
    我和试用期员工之间的故事
    Sogou输入法之父给我们的启示
    《ATL开发指南》的一个值得商榷的地方
    厦门PX项目迁址:意义有限的进步
    探析项目主导型的IT业的人员需求变化及其应对办法
    今天,影响了一位试用期员工的去留
  • 原文地址:https://www.cnblogs.com/topass123/p/12940288.html
Copyright © 2020-2023  润新知