Django+xadmin打造在線教育平台(三)


目錄

在線教育平台(一)      在線教育平台(二)

在線教育平台(三)      在線教育平台(四)

在線教育平台(五)      在線教育平台(六)

在線教育平台(七)      在線教育平台(八)

在線教育平台(九)      在線教育平台(十)

代碼

github下載

教程

學習自慕課網-使用python3.x與Django2.0.1開發的在線教育平台

五、用戶注冊

 主要實現功能

  • 用戶輸入郵箱、密碼和驗證碼,點注冊按鈕
  • 如果輸入的不正確,提示錯誤信息
  • 如果正確,發送激活郵件,用戶通過郵件激活后才能登陸
  • 即使注冊成功,沒有激活的用戶也不能登陸

5.1.初步視圖

users/views.py

class RegisterView(View):
    '''用戶注冊'''
    def get(self,request):
        return render(request,'register.html')

 用戶以get方式,直接返回注冊頁面

5.2.路由設計

# MxOnline/urls.py

from users.views import RegisterView


    path('register/',RegisterView.as_view(),name = 'register'),

urls中。通過類的as_view方法,調用這個View類

5.3.模板修改

修改index.html

點 “注冊 ”應該跳到用戶注冊頁面

 <a style="color:white" class="fr registerbtn" href="/register/">注冊</a>

<a style="color:white" class="fr loginbtn" href="/login/">登錄</a>

修改register.html中的靜態文件地址

{% load staticfiles %}

<link rel="stylesheet" type="text/css" href="{% static 'css/reset.css' %}">
    <link rel="stylesheet" type="text/css" href="{% static 'css/login.css' %}">

.
.
.

<script src="{% static 'js/jquery.min.js' %}" type="text/javascript"></script>
<script src="{% static 'js/unslider.js' %}" type="text/javascript"></script>
<script src="{% static 'js/validateDialog.js' %}"  type="text/javascript"></script>
<script src="{% static 'js/login.js' %}"  type="text/javascript"></script>

測試一下從index界面點注冊能不能跳到register界面

 5.4.驗證碼

 驗證碼庫:django-simple-captcha,這里面有介紹這個第三方庫的使用方法

 安裝:

pip install  django-simple-captcha

Add captcha to the INSTALLED_APPS in your settings.py

INSTALLED_APPS = [
    'captcha',
]

Add an entry to your urls.py:

urlpatterns = [
    path('captcha/',include('captcha.urls')),
]

生成到數據庫

python manage.py makemigrations

python manage.py migrate

可以看到數據庫多了一張表

 

 在注冊頁面顯示驗證碼

 定義我們的register form:

# users/forms.py

from captcha.fields import CaptchaField

class RegisterForm(forms.Form):
    '''注冊驗證表單'''    
    email = forms.EmailField(required=True)
    password = forms.CharField(required=True,min_length=5)
    # 驗證碼,字段里面可以自定義錯誤提示信息
    captcha = CaptchaField()
# users/forms.py

from django import forms
from captcha.fields import CaptchaField


class LoginForm(forms.Form):
    '''登錄驗證表單'''

    username = forms.CharField(required=True)
    password = forms.CharField(required=True,min_length=5)


class RegisterForm(forms.Form):
    '''注冊驗證表單'''

    email = forms.EmailField(required=True)
    password = forms.CharField(required=True,min_length=5)
    # 驗證碼
    captcha = CaptchaField(error_messages={'invalid':'驗證碼錯誤'})
forms.py
通過{{ register_form.captcha }}獲取驗證碼
<div class="form-group marb8 captcha1 ">
     <label>&nbsp;&nbsp;</label>
     {{ register_form.captcha }}
</div>

 

 5.5.完善注冊的后台邏輯

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)
            # 如果用戶已存在,則提示錯誤信息
            if UserProfile.objects.filter(email = user_name):
                return render(request, 'register.html', {'register_form':register_form,'msg': '用戶已存在'})

            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})
# 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})


# 激活用戶
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", )


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)
            # 如果用戶已存在,則提示錯誤信息
            if UserProfile.objects.filter(email = user_name):
                return render(request, 'register.html', {'register_form':register_form,'msg': '用戶已存在'})

            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所以代碼

說明:

  • 如果是get請求,直接返回注冊頁面給用戶
  • 如果是post請求,先生成一個表單實例,並獲取用戶提交的所有信息(request.POST)
  • is_valid()方法,驗證用戶的提交信息是不是合法
  • 如果合法,獲取用戶提交的email和password
  • 實例化一個user_profile對象,把用戶添加到數據庫
  • 默認添加的用戶是激活狀態(is_active=1表示True),在這里我們修改默認的狀態(改為is_active = False),只有用戶去郵箱激活之后才改為True
  • 對密碼加密,然后保存,發送郵箱,username是用戶注冊的郵箱,‘register’表明是注冊
  • 注冊成功跳轉到登錄界面

5.6.發送激活郵件

在Python中已經內置了一個smtp郵件發送模塊,Django在此基礎上進行了簡單地封裝,讓我們在Django環境中可以更方便更靈活的發送郵件。

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

首先settings里面設置

# settings.py

EMAIL_HOST = "smtp.qq.com"  # SMTP服務器主機
EMAIL_PORT = 25             # 端口
EMAIL_HOST_USER = "1184405959@qq.com"       # 郵箱地址
EMAIL_HOST_PASSWORD = "dwjybikexxxxxxxx"    # 密碼
EMAIL_USE_TLS= True
EMAIL_FROM = "1184405959@qq.com"            # 郵箱地址

說明:

   EMAIL_HOST = "smtp.qq.com"

   EMAIL_HOST_PASSWORD = "dwjybikexxxxxxxx"

要想用qq郵箱作為服務器發送郵件,必須先開啟SMTP,方法如下:

1)登錄郵箱,找到“設置”-->>“用戶”

2)往下拉找到SMTP服務,點開啟,然后點“生成授權碼”

3)可以看到授權碼,EMAIL_HOST_PASSWORD里面填寫的就是下面生成的授權碼,而不是你的郵箱密碼

 

在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

 官方文檔:

def send_mail(subject, message, from_email, recipient_list,
              fail_silently=False, auth_user=None, auth_password=None,
              connection=None, html_message=None):

前面四個參數必須要,后面的參數可以為空

發送電子郵件的最簡單方法是使用 django.core.mail.send_mail()

subjectmessagefrom_emailrecipient_list參數是必需的。

  • subject:一個字符串。
  • message:一個字符串。
  • from_email:一個字符串。
  • recipient_list:字符串列表,每個字符串都是電子郵件地址。每個成員都recipient_list將在電子郵件的“收件人:”字段中看到其他收件人。
  • fail_silently:一個布爾值。如果是的話Falsesend_mail會提出一個smtplib.SMTPException。有關smtplib可能的例外列表,請參閱文檔,所有這些例外都是。的子類 SMTPException
  • auth_user:用於向SMTP服務器進行身份驗證的可選用戶名。如果沒有提供,Django將使用該EMAIL_HOST_USER設置的值 。
  • auth_password:用於驗證SMTP服務器的可選密碼。如果沒有提供,Django將使用該EMAIL_HOST_PASSWORD設置的值 。
  • connection:用於發送郵件的可選電子郵件后端。如果未指定,將使用默認后端的實例。有關 更多詳細信息,請參閱電子郵件后端的文檔。
  • html_message:如果html_message被提供,所得到的電子郵件將是一個 多部分/替代電子郵件message作為 文本/無格式內容類型和html_message作為 text / html的內容類型。

返回值將是成功傳遞消息的數量(可以是01因為它只能發送一條消息)。

 5.7.激活用戶

根據郵箱找到對應的用戶,然后設置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

修改register.html

 <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>

 修改的地方說明:

  • value="{{ register_form.email.value }}     
  • value="{{ register_form.password.value }}    注冊的用戶不用再手動輸入一遍郵箱和密碼了 
  • {% if login_form.errors.email %}errorput{% endif %}
  • {% if login_form.errors.password %}errorput{% endif %}
  • {% if login_form.errors.captchal %}errorput{% endif %}    提示錯誤信息並顯示紅框框
  • {{ register_form.captcha }}    顯示驗證碼

添加郵件激活的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'),
]

 

六、找回密碼

主要需要實現的功能:

  • 用戶點“忘記密碼”,跳到找回密碼頁面
  • 在forgetpwd頁面,輸入郵箱和驗證碼成功后,發送郵件提醒
  • 通過點擊郵件鏈接,可以重置密碼
  • 兩次密碼輸的正確無誤后,密碼更新成功,跳到登錄界面

6.1.路由設計

from users.views import ForgetPwdView

urlpatterns = [
    path('forget/',ForgetPwdView.as_view(),name='forget_pwd'),
]

6.2.初步視圖函數

首先也需要個表單

forms.py

class ForgetPwdForm(forms.Form):
    '''忘記密碼'''
    email = forms.EmailField(required=True)
    captcha = CaptchaField(error_messages={'invalid': '驗證碼錯誤'})

視圖函數

class ForgetPwdView(View):
    '''找回密碼'''
    def get(self,request):
        forget_form = ForgetPwdForm()
        return render(request,'forgetpwd.html',{'forget_form':forget_form})

 

get方式,直接返回忘記密碼的表單

6.3.模板修改

修改login.html中的url

<a class="fr" href="{% url 'forget_pwd' %}">忘記密碼?</a>

把forgetpwd.html拷貝到templates文件下

修改靜態文件路徑

顯示驗證碼

 <div class="form-group captcha1 marb38">
     <label>&nbsp;&nbsp;</label>
     {{ forget_pwd.captcha }}
</div>

 

6.4.添加發送找回密碼郵件

修改utils/email_send.py

發送類型為“forget”

    if send_type == "forget":
        email_title = "NBA找回密碼鏈接"
        email_body = "請點擊下面的鏈接找回你的密碼: http://127.0.0.1:8000/reset/{0}".format(code)

        # 使用Django內置函數完成郵件發送。四個參數:主題,郵件內容,從哪里發,接受者list
        send_status = send_mail(email_title, email_body, EMAIL_FROM, [email])
        # 如果發送成功
        if send_status:
            pass
# 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內置函數完成郵件發送。四個參數:主題,郵件內容,從哪里發,接受者list
        send_status = send_mail(email_title, email_body, EMAIL_FROM, [email])
        # 如果發送成功
        if send_status:
            pass

    if send_type == "forget":
        email_title = "NBA找回密碼鏈接"
        email_body = "請點擊下面的鏈接找回你的密碼: http://127.0.0.1:8000/reset/{0}".format(code)

        # 使用Django內置函數完成郵件發送。四個參數:主題,郵件內容,從哪里發,接受者list
        send_status = send_mail(email_title, email_body, EMAIL_FROM, [email])
        # 如果發送成功
        if send_status:
            pass
email_send.py

6.5.完善找回密碼的views

class ForgetPwdView(View):
    '''找回密碼'''
    def get(self,request):
        forget_form = ForgetPwdForm()
        return render(request,'forgetpwd.html',{'forget_form':forget_form})

    def post(self,request):
        forget_form = ForgetPwdForm(request.POST)
        if forget_form.is_valid():
            email = request.POST.get('email',None)
            send_register_eamil(email,'forget')
            return render(request, 'send_success.html')
        else:
            return render(request,'forgetpwd.html',{'forget_form':forget_form})

用戶提交郵箱后,提醒成功發送郵件

新建templates/send_success.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <p>郵件已發送,請注意查收</p>
</body>
</html>

修改forgetpwd.html

 <form id="jsFindPwdForm" method="post" action="{% url 'forget_pwd' %}" autocomplete="off">
                    <input type='hidden' name='csrfmiddlewaretoken' value='mymQDzHWl2REXIfPMg2mJaLqDfaS1sD5'/>
                    <div class="form-group marb20 {% if forget_from.errors.email %}errorput{% endif %}">
                        <label>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</label>
                        <input type="text" id="account" name="email" value="{{ forget_from.email.value }}"
                               placeholder="郵箱"/>
                    </div>
                    <div class="form-group captcha1 marb38 {% if forget_from.errors.captchal %}errorput{% endif %}">
                        <label>&nbsp;&nbsp;</label>
                        {{ forget_form.captcha }}
                    </div>
                    <div class="error btns" id="jsForgetTips">
                        {% for key,error in forget_from.errors.items %}
                            {{ error }}
                        {% endfor %}
                        {{ msg }}
                    </div>
                    <input type="hidden" name="sms_type" value="1">
                    <input class="btn btn-green" id="jsFindPwdBtn" type="submit" value="提交"/>
                    <p class="form-p" style="bottom:40px;">您還可以<a href="login.html"> [直接登錄]</a></p>
                    <input type='hidden' name='csrfmiddlewaretoken' value='5I2SlleZJOMUX9QbwYLUIAOshdrdpRcy'/>
                    {% csrf_token %}
                </form>

測試一下,輸入郵箱和驗證碼看能不能收到郵件

 

6.6.重置密碼

(1)重置密碼激活郵箱的url

 re_path('reset/(?P<active_code>.*)/', ResetView.as_view(), name='reset_pwd'),

(2)寫重置密碼(get方式)后台邏輯

class ResetView(View):
    def get(self, request, active_code):
        all_records = EmailVerifyRecord.objects.filter(code=active_code)
        if all_records:
            for record in all_records:
                email = record.email
                return render(request, "password_reset.html", {"email":email})
        else:
            return render(request, "active_fail.html")
        return render(request, "login.html")

(3)創建修改密碼的form表單

class ModifyPwdForm(forms.Form):
    '''重置密碼'''
    password1 = forms.CharField(required=True, min_length=5)
    password2 = forms.CharField(required=True, min_length=5)

(4)修改密碼的url

上面那個是激活郵箱的url,有active_code參數,只能寫get方式的邏輯。

這里必須單獨新建一個修改密碼的url,因為如果以post方式提交的話,post提交的地方跟get方式(url中需要active_code參數)的地址不一樣,action="{% url 'modify_pwd' %}

path('modify_pwd/', ModifyPwdView.as_view(), name='modify_pwd'),

(5)修改密碼的后台邏輯

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 = UserProfile.objects.get(email=email)
            user.password = make_password(pwd2)
            user.save()

            return render(request, "login.html")
        else:
            email = request.POST.get("email", "")
            return render(request, "password_reset.html", {"email":email, "modify_form":modify_form })

(6)修改password_reset.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
    <title>密碼修改</title>
    <link rel="stylesheet" type="text/css" href="/static/css/reset.css">
    <link rel="stylesheet" type="text/css" href="/static/css/animate.css">
    <link rel="stylesheet" type="text/css" href="/static/css/style.css">

<body>
<div class="wp">
    <div class="resetpassword" id="resetPwdForm">
        <h1>修改密碼</h1>
        <p>已經通過驗證,請設置新密碼</p>
        <form id="reset_password_form" action="{% url 'modify_pwd' %}" method="post">
            <ul>
                <li class="{% if modify_form.errors.password1 %}errorput{% endif %}">
                    <span class="">新 密 碼 :</span>
                    <input type="password" name="password1" id="pwd" placeholder="6-20位非中文字符">
                    <i></i>
                </li>
                <input type="hidden" name="email" value="{{ email }}">
                <li class="{% if modify_form.errors.password2 %}errorput{% endif %}">
                    <span class="">確定密碼:</span>
                    <input type="password" name="password2" id="repwd" placeholder="6-20位非中文字符">
                    <i></i>
                </li>
                <div class="error btns" id="jsPasswdResetTips">
                    {% for key,error in modify_form.errors.items %}{{ key }}:{{ error }}{% endfor %}{{ msg }}</div>
                <li class="button">
                    <input type="submit" value="提交">
                </li>
            </ul>
            {% csrf_token %}
        </form>
    </div>
    <div class="resetpassword" id="reset_password_tips" style="display:none;">
        <h1>修改密碼成功,請重新登錄</h1>
        <img class="fl" src="/static/images/check2.png">
        <p class="successword">已經成功修改密碼,請重新登錄</p>
    </div>
</div>
</body>
</html>

看一下整個流程有沒有問題

首先在login界面點“忘記密碼”,跳到forget頁面

 

 

 

然后填上要找回密碼的郵箱和驗證碼,提交后會收到郵件

點擊鏈接,跳到修改密碼頁面

修改密碼后,跳轉到login頁面

 

             Django+xadmin打造在線教育平台(二)                  Django+xadmin打造在線教育平台(一)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM