02 用戶註冊通過發送郵箱激活
配置靜態文件
在項目根目錄下創建靜態文件static目錄,用於放置靜態的文件
在settings 文件中定義靜態內容
STATIC_URL = ‘/static/‘ STATICFILES_DIRS = [ os.path.join(BASE_DIR, ‘static‘), ]
把靜態的文件如css,js,image放入static目錄中:
把當前關於註冊用到的模板放到模板文件中,
在應用users中 views視圖定義處理註冊的請求函數,返回註冊的頁面:
類視圖:http://python.usyiyi.cn/translate/django_182/topics/class-based-views/intro.html
# 導入類視圖,主要給urls from django.views.generic import View class RegisterView(View): """註冊""" def get(self, request): """對應get請求方式,提供註冊頁面""" return render(request, "register.html", )
在根級urls中配置到應用users的跳轉路徑
import users.urls url(r‘^users/‘, include(users.urls, namespace="users")),
在uers.urls.py中配置請求路徑
from django.conf.urls import url from . import views urlpatterns = [ url(r‘^register$‘, views.RegisterView.as_view(), name="register"), ]
在瀏覽器地址欄中輸入:
http://127.0.0.1:8000/users/register
返回的頁面如下所示:
註冊頁中的html代碼如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"View Code> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <title>天天生鮮-註冊</title> <link rel="stylesheet" type="text/css" href="../static/css/reset.css"> <link rel="stylesheet" type="text/css" href="../static/css/main.css"> <script type="text/javascript" src="../static/js/jquery-1.12.4.min.js"></script> <script type="text/javascript" src="../static/js/register.js"></script> </head> <body> <div class="register_con"> <div class="l_con fl"> <a class="reg_logo"><img src="../static/images/logo02.png"></a> <div class="reg_slogan">足不出戶 · 新鮮每一天</div> <div class="reg_banner"></div> </div> <div class="r_con fr"> <div class="reg_title clearfix"> <h1>用戶註冊</h1> <a href="#">登錄</a> </div> <div class="reg_form clearfix"> <form method="post"> {% csrf_token %} <ul> <li> <label>用戶名:</label> <input type="text" name="user_name" id="user_name"> <span class="error_tip">提示信息</span> </li> <li> <label>密碼:</label> <input type="password" name="pwd" id="pwd"> <span class="error_tip">提示信息</span> </li> <li> <label>確認密碼:</label> <input type="password" name="cpwd" id="cpwd"> <span class="error_tip">提示信息</span> </li> <li> <label>郵箱:</label> <input type="text" name="email" id="email"> <span class="error_tip">提示信息</span> {{ errmsg }} </li> <li class="agreement"> <input type="checkbox" name="allow" id="allow" checked="checked"> <label>同意”天天生鮮用戶使用協議“</label> <span class="error_tip2">提示信息</span> </li> <li class="reg_sub"> <input type="submit" value="註 冊" name=""> </li> </ul> </form> </div> </div> </div> <div class="footer no-mp"> <div class="foot_link"> <a href="#">關於我們</a> <span>|</span> <a href="#">聯系我們</a> <span>|</span> <a href="#">招聘人才</a> <span>|</span> <a href="#">友情鏈接</a> </div> <p>CopyRight © 2016 北京天天生鮮信息技術有限公司 All Rights Reserved</p> <p>電話:010-****888 京ICP備*******8號</p> </div> </body> </html>
用戶提交表單的時候接受發送的post請求,由於表單中action表單的地址沒寫,所以還在原來的請求地址和視圖函數中處理,只不過是post的請求而已,
在視圖函數中,添加post請求處理的函數:
from django.core.urlresolvers import reverse from django import db from .models import * import re def post(self, request): """對應post請求方式,接收處理用戶的註冊數據""" # 接收傳入的參數 user_name = request.POST.get("user_name") password = request.POST.get("pwd") email = request.POST.get("email") allow = request.POST.get("allow") # 檢驗參數的正確性 if not all([user_name, password, email]): # 重定向到註冊頁面 return redirect(reverse("users:register")) if not re.match(r"^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$", email): # 返回錯誤信息 return render(request, "register.html", {"errmsg": "郵箱格式不正確"}) if allow != "on": return render(request, "register.html", {"errmsg": "請接收註冊協議!"}) # 進行業務邏輯處理,將數據保存到數據庫 # 註意用戶的密碼要加密, try: # django的AbstractUser基類提供的創建用戶的方法 user = User.objects.create_user(user_name, email, password) except db.IntegrityError: # 如果用戶名已存在,則拋出此異常信息 return render(request, "register.html", {"errmsg": "用戶名已存在!"}) # 將用戶的激活狀態設置為假 user.is_active = False user.save() # 將結果返回給前端 return redirect(reverse("goods:index"))View Code
在根基目錄的urls中,構造商品應用的請求地址
import goods.urls urlpatterns = [ url(r‘^‘, include(goods.urls, namespace=‘goods‘)), ]
在商品的views中,構造商品主頁的請求函數
from django.shortcuts import render from django.views.generic import View class IndexView(View): def get(self,request): return render(request,‘index.html‘)
在應用goods中的urls中,構造商品主頁的請求地址
from django.conf.urls import url from goods import views urlpatterns = [ url(r"^$", views.IndexView.as_view(), name="index"), ]
註冊成功在數據庫中的查詢狀態:
使用celery實現異步調用django的發送郵件的模塊,讓用戶激活自己的賬號.
主要思想是,先生成一個唯一的口令用來表示用戶,通過django中的(itsdangerous模塊),在使用celery服務器實現異步發送郵件.
1 根據用戶的ID生成唯一的口令:
在用戶模模型類中,創建生成唯一口令的方法:
用戶生成註冊口令文檔 http://itsdangerous.readthedocs.io/en/latest/
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer class User(AbstractUser, BaseModel): """用戶""" class Meta: db_table = "df_users" def generate_active_token(self): """生成激活令牌""" # 構建序列化器(轉換工具)對象 serializer = Serializer(settings.SECRET_KEY, 3600) # 轉換參數 token = serializer.dumps({"confirm": self.id}) # 返回bytes類型 return token.decode()View Code
2 在項目根目錄下創建celery_tasks的包用來存儲用celery發送任務的模塊,在包中創建tasks.py模塊其內容為:
from celery import Celery import os #把jiango的配置模型放到系統的環境變量中,celery才可以調用django的模塊 os.environ["DJANGO_SETTINGS_MODULE"] = "dailyfresh_13.settings" # 放到celery服務器上時將註釋打開 # import django # django.setup() from django.core.mail import send_mail from django.conf import settings # 創建celery應用對象 app = Celery("celery_tasks.tasks", broker="redis://10.211.55.5/2") # 定義任務 @app.task def send_active_email(user_name, to_email, token): """發送激活郵件""" subject = "天天生鮮用戶激活" # 郵件標題 body = "" # 郵件體 sender = settings.EMAIL_FROM # 發件人 receivers = [to_email] # 接收人 html_body = ‘<h1>尊敬的用戶 %s, 感謝您註冊天天生鮮!</h1>‘ ‘<br/><p>請點擊此鏈接激活您的帳號<a href="http://127.0.0.1:8000/users/active/%s">‘ ‘http://127.0.0.1:8000/users/active/%s<a></p>‘ % (user_name, token, token) # html郵件體 send_mail(subject, body, sender, receivers, html_message=html_body)View Code
3 調用celery任務入到broker隊列中,以便剛才我們創建的celery workder服務器能夠從隊列中取出任務並執行。如何將任務函數加入到隊列中,可使用delay()
在用戶註冊的post請求處理函數中,將發送郵件的任務函數加入到隊列中,
把下面的兩行代碼加到 class RegisterView(View):的post請求函數中
from celery_tasks.tasks import send_active_email # 為用戶生成激活口令 token = user.generate_active_token() # 使用celery異步發送郵件 send_active_email.delay(user_name, email, token)
4 打開項目的settings.py文件,配置Email:
# Email EMAIL_BACKEND = ‘django.core.mail.backends.smtp.EmailBackend‘ EMAIL_HOST = ‘smtp.126.com‘ EMAIL_PORT = 25 #發送郵件的郵箱 EMAIL_HOST_USER = ‘[email protected]‘ #在郵箱中設置的客戶端授權密碼 EMAIL_HOST_PASSWORD = ‘ITCAST123‘ #收件人看到的發件人 EMAIL_FROM = ‘天天生鮮<[email protected]>‘
5 處理用戶激活的請求:
定義用戶激活的請求的處理函數:
# 口令過期 from itsdangerous import SignatureExpired # 定義了激活的接口 class ActiveView(View): """激活""" def get(self, request, token): """ :param request: :param token: token是用戶攜帶的口令,唯一標識用戶 :return: """ # 解析口令token,獲取用戶身份 # 構建序列化器 s = Serializer(settings.SECRET_KEY) try: data = s.loads(token) except SignatureExpired: # 表示token過期 return HttpResponse("鏈接已過期!") # 表示token未過期, user_id = data.get("confirm") # 查詢用戶的數據.處理bug try: user = User.objects.get(id=user_id) except User.DoesNotExist: # 用戶不存在 return HttpResponse("用戶不存在!") # 設置用戶的激活狀態 user.is_active = True user.save() # 返回處理結果 return HttpResponse("ok") # return redirect(reverse("users:login"))
6 配置用戶激活請求的url:
url(r‘^active/(?P<token>.+)‘, views.ActiveView.as_view(), name="active"),
5 .打開終端,執行命令:
celery -A celery_tasks.tasks worker --loglevel=info
用戶dsa提交表單:
celery發送郵件成功:
用戶dsa接受到郵件點擊激活後,查詢數據庫中的is_active的狀態為1,激活成功:
定義用戶登陸請求的處理函數:
Django認證系統文檔 http://python.usyiyi.cn/documents/django_182/topics/auth/default.html
from django.contrib.auth import authenticate, login class LoginView(View): """登錄""" def get(self, request): """提供登錄頁面""" return render(request, "login.html") def post(self, request): """處理登錄的數據""" # 獲取參數 user_name = request.POST.get("username") password = request.POST.get("pwd") # 參數校驗 if not all([user_name, password]): # 參數不完整 return render(request, "login.html") # 登錄業務邏輯處理 # try: # password = sha256(password) # User.objects.get(username=user_name, password=password) # except User.DoesNotExist: # return HttpResponse("用戶名或密碼錯誤") # 使用django的認證系統進行用戶密碼的校驗 user = authenticate(username=user_name, password=password) if user is None: # 用戶的登錄信息有誤 return render(request, "login.html", {"errmsg": "用戶名或密碼錯誤!"}) # 判斷用戶的激活狀態 if user.is_active is False: return render(request, "login.html", {"errmsg": "用戶尚未激活!"}) # 保存用戶的登錄狀態 # 使用django的login函數保存用戶的session數據 login(request, user) # 登錄成功,跳轉到主頁 return HttpResponse(‘登陸成功‘) #return redirect(reverse("goods:index"))
在瀏覽器輸入以下的網址:
http://127.0.0.1:8000/users/login
用戶和激活的狀態判斷成功後,顯示以下的頁面:
配置用戶登陸請求的url:
url(r‘^login$‘, views.LoginView.as_view(), name="login"),
======================================================================================================
用戶登陸成功,返回主頁的請求處理函數,這個請求處理函數寫在goods應用中的views函數中:
from django.shortcuts import render from django.views.generic import View # Create your views here. class IndexView(View): """主頁""" def get(self, request): return render(request, "index.html")
定義用戶登陸主頁的請求路徑:
現在根據的請求路徑urls中,定義再跳到goods應用中的urls
在根基定義跳轉的路徑:
url(r‘^/‘, include(goods.urls, namespace="goods")),
在goods應用中的urls模塊中寫請求登陸主頁的路徑:
from django.conf.urls import url from goods import views urlpatterns = [ url(r"^$", views.IndexView.as_view(), name="index"), ]
在用戶登陸處理函數login中把最後的登陸成功的路徑跳轉到主頁
# return HttpResponse(‘登陸成功‘) return redirect(reverse(‘goods:index‘))
點擊登陸,認證成功後,返回以下的頁面:
============================================================
把session和緩存儲在redis數據庫中,在setings中配置代碼以下:
pip install django-redis
django-redis文檔:http://django-redis-chs.readthedocs.io/zh_CN/latest/#
django的session使用文檔:http://python.usyiyi.cn/documents/django_182/topics/http/sessions.html
CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://localhost/3", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } } } # Session # http://django-redis-chs.readthedocs.io/zh_CN/latest/#session-backend SESSION_ENGINE = "django.contrib.sessions.backends.cache" SESSION_CACHE_ALIAS = "default"
用戶登陸成功後,在redis數據庫中的查詢的結果如下:
02 用戶註冊通過發送郵箱激活