Django第5章: auth補充之用戶註冊,密碼找回
阿新 • • 發佈:2018-04-07
war def title 必須 elb errors res random 綁定
自定義以郵箱和密碼登錄用戶
1. 重載authenticate()
from django.contrib.auth.backends import ModelBackend from django.db.models import Q from userinfo.models import UserProfile class CustomBackend(ModelBackend): def authenticate(self, request, username=None, password=None, **kwargs): # 以username或者email字段匹配用戶輸入的usernma內容 user = UserProfile.objects.filter(Q(username=username)|Q(email=username)).first() # 匹配出用戶記錄後再進一步匹配密碼 if user.check_password(password): # 返回用戶 return user else: return None
2. 修改配置文件
AUTHENTICATION_BACKENDS = (
'userinfo.views.CustomBackend',
)
外部驗證碼模塊應用
django-simple-captcha模塊
- 安裝模塊:
pip install django-simple-captcha
; - 增加
captcha
到INSTALLED_APPS
中; - 生成captcha表:
manage.py migrate
; 配置
urls.py
:urlpatterns += [ url(r'^captcha/', include('captcha.urls')), ]
設置
cpatcha
的model
from captcha.fields import CaptchaField from django import forms class RegisterForm(forms.Form): username = forms.CharField(max_length=12, min_length=2, required=True) password = forms.CharField(min_length=4, required=True) captcha = CaptchaField()
在模板直接導入
{{RegisterForm.captcha}}
驗證碼的錯誤這個模塊會自行進行校驗,無須自己手動寫邏輯;
註冊邏輯
// views.py
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():
email = register_form.cleaned_data.get('email', '')
// 過濾重復註冊
if UserProfile.objects.filter(email=email):
return render(request, 'register.html', {'msg':'用戶已註冊', 'register_form':register_form})
else:
password = register_form.cleaned_data.get('password', '')
# 新建用戶
new_user = UserProfile()
new_user.username = email
new_user.email = email
# 非常重要, 用戶沒有激活鏈接前必須為False
new_user.is_active = False
# 對密碼進行加密處理,利用django自帶的加密方法
new_user.password = make_password(password)
new_user.save()
# 發送郵件進行激活驗證
send_email(email, 'register')
return render(request, 'send_email_success.html')
else:
# form自行檢測字段不合格
return render(request, 'register.html', {'register_form': register_form})
// register.html
<form method="post" action="{% url 'register' %}" autocomplete="off">
<!--若用戶名form表單出現錯誤信息,則加上errorput屬性-->
<div class="form-group marb20 {% if register_form.errors.email %}errorput{% endif %}">
<label>郵 箱</label>
<input type="text" id="id_email" name="email" value="" placeholder="請輸入您的郵箱地址" autocomplete="On" />
</div>
<!--同上-->
<div class="form-group marb8 {% if register_form.errors.password %}errorput{% endif %}">
<label>密 碼</label>
<input type="password" id="id_password" name="password" value="" placeholder="請輸入6-20位非中文字符密碼" />
</div>
<div class="form-group marb8 captcha1 {% if register_form.errors.captcha %}errorput{% endif %}">
<label>驗 證 碼</label>
{{ register_form.captcha }}
</div>
<!-- 循環列出表單的報錯信息 -->
<div class="error btns" id="jsEmailTips"> {{ msg }} {% for key, value in register_form.errors.items %} {{ key }}{{ value }} {% endfor %}</div>
<div class="auto-box marb8">
</div>
<input class="btn btn-green" id="jsEmailRegBtn" type="submit" value="註冊並登錄" />
{% csrf_token %}
</form>
發送郵件
setting文件配置
EMAIL_HOST = "smtp.qq.com"
EMAIL_PORT = 25
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = 'qgmlmnhulqupbdij'
EMAIL_USE_TLS = True
EMAIL_FROM = EMAIL_HOST_USER
發送郵件邏輯
# send_email.py
// 由激活視圖函數通過驗證後才調用此函數
from datetime import datetime
import random, string
from django.core.mail import send_mail # django自帶的郵件發送模塊
from onlineLearningSys.settings import EMAIL_FROM
from userinfo.models import EmailVerifyRecord
def generate_random_str(num):
# 生成特定位數的字符串
return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(num))
def send_email(email, send_type = ''):
if type == "change_email":
code = generate_random_str(4)
else:
code = generate_random_str(16)
# 實例化郵件激活碼對象,並在數據庫生成記錄
email_verify_record = EmailVerifyRecord()
email_verify_record.email = email
email_verify_record.code = code
email_verify_record.send_type = send_type
email_verify_record.send_time = datetime.now()
email_verify_record.save()
email_title = ""
email_body = ""
if send_type == 'register':
email_title = 'MXonline在線網註冊激活連接'
email_body = '請點擊下面的鏈接重置密碼: http://127.0.0.1:8000/user/activate/{0}'.format(code)
# 固定格式書寫
send_status = send_mail(email_title, email_body, EMAIL_FROM, [email])
if send_status:
print('發送成功')
elif send_type == 'forget':
email_title = 'MXonline在線網密碼重置連接'
// 當用戶點擊此網址時候,會觸發對應的視圖函數,並且接收到對應的值;
email_body = '請點擊下面的鏈接激活的你的賬號: http://127.0.0.1:8000/user/reset/{0}'.format(code)
send_status = send_mail(email_title, email_body, EMAIL_FROM, [email])
if send_status:
print('發送成功')
elif send_type == 'change_email':
email_title = 'MXonline在線網綁定郵箱更改鏈接'
email_body = '請復制您的驗證碼 : {0}'.format(code)
send_status = send_mail(email_title, email_body, EMAIL_FROM, [email])
if send_status:
print('發送成功')
激活用戶
每發送一次郵件, 都會生成
email_verify_record
對象,包括email
,code
和send_type
三個字段,保存在數據庫;配置
url(r‘^activate/(\S{16})/‘, ActivateView.as_view(), name=‘activate‘),
, 由對應的視圖函數接收16位驗證碼;激活邏輯
class ActivateView(View): def get(self, request, code): email_record = EmailVerifyRecord.objects.filter(code=code) # 根據傳過來的code在數據庫中取出相應的郵件激活記錄 if email_record: record = email_record.first() email = record.email user = UserProfile.objects.get(email=email) user.is_active = True print('激活成功') user.save() return redirect('/user/login/') else: return render(request, 'register.html')
密碼找回
若忘記密碼.需要提交郵箱和驗證碼,進行發送郵件
class ForgetPwd(View): # 忘記密碼 def get(self, request): forget_p_form = ForgetPwdForm() return render(request, 'forgetpwd.html', {'forget_p_form': forget_p_form}) def post(self, request): forget_p_form = ForgetPwdForm(request.POST) if forget_p_form.is_valid(): email = forget_p_form.cleaned_data.get("email", '') # 根據郵箱信息進行用戶過濾 user = UserProfile.objects.filter(Q(username=email)|Q(email=email)) if user: send_email(email, 'forget') return render(request, 'send_email_success.html') else: # 用戶不存在 return render(request, 'forgetpwd.html', {'forget_p_form': forget_p_form, 'msg': '對不起,該郵箱未被註冊'}) else: return render(request, 'forgetpwd.html', {'forget_p_form': forget_p_form})
用戶收到激活地址後,進入重置密碼頁面,此時將email渲染如模板中
# 第一次訪問時候先將用戶的email的值渲染進模板裏保存起來 urlpatterns = [url(r'^reset/(\S{16})/', ResetPwd.as_view()),] # 此處必須單獨寫一個get函數,僅限於用戶第一次點擊激活地址進入 class ResetPwd(View): def get(self, request, code): # 進入密碼重置界面 # 獲取郵箱驗證記錄 email_record = EmailVerifyRecord.objects.filter(code=code) if email_record: record = email_record.first() email = record.email # 通過註冊郵箱找到用戶 user = UserProfile.objects.filter(email=email) if user: # 存在相關用戶,跳轉至登錄頁面 return render(request, 'password_reset.html', {"email":email}) // html <form id="reset_password_form" action="{% url 'reset-pwd' %}" method="post"> <ul> <li> <span class="">新 密 碼 :</span> <input type="password" name="password_1" id="pwd" placeholder="6-20位非中文字符"> <i>{{ pwd_reset_form.errors.password_1 }}</i> </li> <input name="email" type="hidden" value="{{ email }}"> <li> <span class="">確定密碼:</span> <input type="password" name="password_2" id="repwd" placeholder="6-20位非中文字符"> <i>{{ pwd_reset_form.errors.password_1 }}</i> <i>{{ msg }}</i> </li> <li class="button"> <input type="submit" value="提交" onclick="reset_password_form_submit()"> </li> </ul> {% csrf_token %} </form>
提交重置表單
// urls.py urlpatterns = [url(r'^reset/', ResetPwdView.as_view(), name='reset-pwd'), ] // views.py class ResetPwdView(View): def post(self, request): pwd_reset_form = PwdResetForm(request.POST) email = request.POST.get('email', '') if pwd_reset_form.is_valid(): password_1 = pwd_reset_form.cleaned_data.get('password_1') password_2 = pwd_reset_form.cleaned_data.get('password_2') if password_1 == password_2: user = UserProfile.objects.filter(Q(email=email)|Q(username=email)) if user: user = user.first() user.password = make_password(password_1) user.save() print('密碼修改成功') return render(request, 'login.html') else: # 用戶不存在 return render(request, 'password_reset.html', {'msg':'用戶不存在'}) else: return render(request, 'password_reset.html', {'msg': '密碼輸入不一致', 'pwd_reset_form':pwd_reset_form, 'email':email}) else: return render(request, 'password_reset.html', {'pwd_reset_form':pwd_reset_form, 'email':email})
Django第5章: auth補充之用戶註冊,密碼找回