小白學Python-使用Django實現商城郵箱驗證功能

添加郵箱後端邏輯

1. 添加郵箱接口設計和定義

1.請求方式
選項 方案
請求方法 PUT
請求地址 /emails/
2.請求參數
參數名 類型 是否必傳 說明
email string 郵箱
3.響應結果:JSON
字段 說明
code 狀態碼
errmsg 錯誤信息

2. 添加郵箱後端邏輯實現

class EmailView(View):
    """添加郵箱"""

    def put(self, request):
        """實現添加郵箱邏輯"""
        # 接收參數
        json_dict = json.loads(request.body.decode())
        email = json_dict.get('email')

        # 校驗參數
        if not email:
            return http.HttpResponseForbidden('缺乏email參數')
        if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
            return http.HttpResponseForbidden('參數email有誤')

        # 賦值email字段
        try:
            request.user.email = email
            request.user.save()
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '添加郵箱失敗'})

        # 響應添加郵箱結果
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '添加郵箱成功'})

3. 判斷用戶是否登陸並返回JSON

重要提示:
  • 只有用戶登陸時才能讓其綁定郵箱。
  • 此時先後端交互的數據類型是JSON,因此須要判斷用戶是否登陸並返回JSON給用戶。

方案一:html

  • 使用Django用戶認證系統提供的is_authenticated()
class EmailView(View):
    """添加郵箱"""

    def put(self, request):
        """實現添加郵箱邏輯"""
        # 判斷用戶是否登陸並返回JSON
        if not request.user.is_authenticated():
            return http.JsonResponse({'code': RETCODE.SESSIONERR, 'errmsg': '用戶未登陸'})
        pass

方案二:python

  • 自定義返回JSON的login_required裝飾器
  • meiduo_mall.utils.views.py
def login_required_json(view_func):
    """
    判斷用戶是否登陸的裝飾器,並返回json
    :param view_func: 被裝飾的視圖函數
    :return: json、view_func
    """
    # 恢復view_func的名字和文檔
    @wraps(view_func)
    def wrapper(request, *args, **kwargs):

        # 若是用戶未登陸,返回json數據
        if not request.user.is_authenticated():
            return http.JsonResponse({'code': RETCODE.SESSIONERR, 'errmsg': '用戶未登陸'})
        else:
            # 若是用戶登陸,進入到view_func中
            return view_func(request, *args, **kwargs)

    return wrapper


class LoginRequiredJSONMixin(object):
    """驗證用戶是否登錄並返回json的擴展類"""
    @classmethod
    def as_view(cls, **initkwargs):
        view = super().as_view(**initkwargs)
        return login_required_json(view)
LoginRequiredJSONMixin的使用
class EmailView(LoginRequiredJSONMixin, View):
    """添加郵箱"""

    def put(self, request):
        """實現添加郵箱邏輯"""
        # 判斷用戶是否登陸並返回JSON
        pass

Django發送郵件的配置

1. Django發送郵件流程分析

image-20210603225738764

send_mall()方法介紹django

  • 位置:json

    • django.core.mail模塊提供了send_mail()來發送郵件。
  • 方法參數:後端

    • send_mail(subject, message, from_email, recipient_list, html_message=None)
subject 郵件標題
message 普通郵件正文,普通字符串
from_email 發件人
recipient_list 收件人列表
html_message 多媒體郵件正文,能夠是html字符串

2. 準備發郵件服務器

1.點擊進入《設置》界面

image-20210603225959079

2.點擊進入《客戶端受權密碼》界面

image-20210603230006574

3.開啓《受權碼》,並完成驗證短信

image-20210603225834209

4.填寫《受權碼》

image-20210603225842706

5.完成《受權碼》設置

image-20210603225856482

6.配置郵件服務器
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' # 指定郵件後端
EMAIL_HOST = 'smtp.163.com' # 發郵件主機
EMAIL_PORT = 25 # 發郵件端口
EMAIL_HOST_USER = 'hmmeiduo@163.com' # 受權的郵箱
EMAIL_HOST_PASSWORD = 'hmmeiduo123' # 郵箱受權時得到的密碼,非註冊登陸密碼
EMAIL_FROM = '美多商城<hmmeiduo@163.com>' # 發件人擡頭

發送郵箱驗證郵件

重要提示:
  • 發送郵箱驗證郵件是耗時的操做,不能阻塞美多商城的響應,因此須要異步發送郵件
  • 咱們繼續使用Celery實現異步任務。

1. 定義和調用發送郵件異步任務

1.定義發送郵件任務
@celery_app.task(bind=True, name='send_verify_email', retry_backoff=3)
def send_verify_email(self, to_email, verify_url):
    """
    發送驗證郵箱郵件
    :param to_email: 收件人郵箱
    :param verify_url: 驗證連接
    :return: None
    """
    subject = "商城郵箱驗證"
    html_message = '<p>尊敬的用戶您好!</p>' \
                   '<p>感謝您使用商城。</p>' \
                   '<p>您的郵箱爲:%s 。請點擊此連接激活您的郵箱:</p>' \
                   '<p><a href="%s">%s<a></p>' % (to_email, verify_url, verify_url)
    try:
        send_mail(subject, "", settings.EMAIL_FROM, [to_email], html_message=html_message)
    except Exception as e:
        logger.error(e)
        # 有異常自動重試三次
        raise self.retry(exc=e, max_retries=3)

2.註冊發郵件的任務:main.pybash

  • 在發送郵件的異步任務中,咱們用到了Django的配置文件。
  • 因此咱們須要修改celery的啓動文件main.py。
  • 在其中指明celery能夠讀取的Django配置文件。
  • 最後記得註冊新添加的email的任務
# celery啓動文件
from celery import Celery


# 爲celery使用django配置文件進行設置
import os
if not os.getenv('DJANGO_SETTINGS_MODULE'):
    os.environ['DJANGO_SETTINGS_MODULE'] = 'meiduo_mall.settings.dev'

# 建立celery實例
celery_app = Celery('meiduo')

# 加載celery配置
celery_app.config_from_object('celery_tasks.config')

# 自動註冊celery任務
celery_app.autodiscover_tasks(['celery_tasks.sms', 'celery_tasks.email'])
3.調用發送郵件異步任務
# 賦值email字段
try:
    request.user.email = email
    request.user.save()
except Exception as e:
    logger.error(e)
    return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '添加郵箱失敗'})

# 異步發送驗證郵件
verify_url = '郵件驗證連接'
send_verify_email.delay(email, verify_url)

# 響應添加郵箱結果
return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '添加郵箱成功'})
4.啓動Celery
$ celery -A celery_tasks.main worker -l info

2. 生成郵箱驗證連接

1.定義生成郵箱驗證連接方法
def generate_verify_email_url(user):
    """
    生成郵箱驗證連接
    :param user: 當前登陸用戶
    :return: verify_url
    """
    serializer = Serializer(settings.SECRET_KEY, expires_in=constants.VERIFY_EMAIL_TOKEN_EXPIRES)
    data = {'user_id': user.id, 'email': user.email}
    token = serializer.dumps(data).decode()
    verify_url = settings.EMAIL_VERIFY_URL + '?token=' + token
    return verify_url
2.配置相關參數
# 郵箱驗證連接
EMAIL_VERIFY_URL = 'http://www.shagncheng.site:8000/emails/verification/'
3.使用郵箱驗證連接
verify_url = generate_verify_email_url(request.user)
send_verify_email.delay(email, verify_url)

驗證郵箱後端邏輯

1. 驗證郵箱接口設計和定義

1.請求方式
選項 方案
請求方法 GET
請求地址 /emails/verification/
2.請求參數:查詢參數
參數名 類型 是否必傳 說明
token string 郵箱激活連接
3.響應結果:HTML
字段 說明
郵箱驗證失敗 響應錯誤提示
郵箱驗證成功 重定向到用戶中心

2. 驗證連接提取用戶信息

def check_verify_email_token(token):
    """
    驗證token並提取user
    :param token: 用戶信息簽名後的結果
    :return: user, None
    """
    serializer = Serializer(settings.SECRET_KEY, expires_in=constants.VERIFY_EMAIL_TOKEN_EXPIRES)
    try:
        data = serializer.loads(token)
    except BadData:
        return None
    else:
        user_id = data.get('user_id')
        email = data.get('email')
        try:
            user = User.objects.get(id=user_id, email=email)
        except User.DoesNotExist:
            return None
        else:
            return user

3. 驗證郵箱後端邏輯實現

驗證郵箱的核心:就是將用戶的 email_active字段設置爲 True
class VerifyEmailView(View):
    """驗證郵箱"""

    def get(self, request):
        """實現郵箱驗證邏輯"""
        # 接收參數
        token = request.GET.get('token')

        # 校驗參數:判斷token是否爲空和過時,提取user
        if not token:
            return http.HttpResponseBadRequest('缺乏token')

        user = check_verify_email_token(token)
        if not user:
            return http.HttpResponseForbidden('無效的token')

        # 修改email_active的值爲True
        try:
            user.email_active = True
            user.save()
        except Exception as e:
            logger.error(e)
            return http.HttpResponseServerError('激活郵件失敗')

        # 返回郵箱驗證結果
        return redirect(reverse('users:info'))
關注公衆號:測試老憨,回覆:商城,獲取完成項目代碼
相關文章
相關標籤/搜索