django-用戶認(rèn)證系統(tǒng)(注冊(cè),登錄,校驗(yàn),celery發(fā)送郵件,session保存到redis)

項(xiàng)目開發(fā)中視圖處理一般流程:
1.接收參數(shù)
2.參數(shù)校驗(yàn)(后端校驗(yàn))
3.處理業(yè)務(wù)邏輯
4.返回應(yīng)答

  1. 為了將項(xiàng)目里面的文件夾加入django自動(dòng)搜索路徑
    import os
    import sys
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file)))
    sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))
    [圖片上傳失敗...(image-4e83bb-1520673419181)]

1.接收參數(shù)
2.參數(shù)校驗(yàn)(后端校驗(yàn))
校驗(yàn)數(shù)據(jù)完整性
校驗(yàn)郵箱格式
3.業(yè)務(wù)處理:注冊(cè)
django認(rèn)證系統(tǒng):
create_user: 創(chuàng)建用戶
authenticate: 登錄驗(yàn)證
login: 記住用戶登錄狀態(tài)
logout: 清除用戶登錄狀態(tài)
[http://python.usyiyi.cn/documents/django_182/topics/auth/default.html]
注意: 如果authenticate返回None, 可能是User.objects.create_user()里面的參數(shù)順序不對(duì)
4.返回應(yīng)答

celery:
[圖片上傳失敗...(image-7df1ef-1520673419182)]

bug: 兩個(gè)應(yīng)用名錯(cuò)誤, 注冊(cè)的時(shí)候忘記逗號(hào)

登錄校驗(yàn):
request對(duì)象有一個(gè)user屬性, request.user
如果用戶已登錄, 是一個(gè)認(rèn)證用戶模型類(User)的對(duì)象, 包含登錄用戶的信息
如果未登錄,request.user是一個(gè)匿名用戶(AnonymousUser)類的一個(gè)實(shí)例
request.user.is_authenticated:
User類的該屬性是True
AnonymousUser類的該屬性是False
在模板文件中可以直接使用一個(gè)模板變量user, 實(shí)際上就是request.user[圖片上傳失敗...(image-8fe137-1520673419182)]

將session存到redis數(shù)據(jù)庫(kù)
http://django-redis-chs.readthedocs.io/zh_CN/latest/
安裝包:pip install django-redis

django發(fā)送郵件(SMTP服務(wù)器)

1.導(dǎo)入包
from django.core.mail import send_mail

2.獲取163SMTP客戶端授權(quán)碼
[圖片上傳失敗...(image-3aece2-1520673419182)][圖片上傳失敗...(image-7c3340-1520673419182)]
[圖片上傳失敗...(image-bab5df-1520673419182)]
[圖片上傳失敗...(image-e01cca-1520673419182)]

3.配置項(xiàng)目的setting.py,添加如下配置

# 發(fā)送郵件配置
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.163.com'
EMAIL_PORT = 25
# 發(fā)送郵件的郵箱
EMAIL_HOST_USER = '郵箱地址'
# 在郵箱中設(shè)置的客戶端授權(quán)密碼
EMAIL_HOST_PASSWORD = '密碼'
# 收件人看到的發(fā)件人
EMAIL_FROM = '名稱<郵箱地址>'

4.在應(yīng)用views.py中新建send函數(shù)

from django.conf import settings
from django.core.mail import send_mail
from django.http import HttpResponse
...
def send(request):
    send_mail(subject='郵件標(biāo)題',
                message='郵件html會(huì)轉(zhuǎn)義正文',
                from_email='發(fā)件人',
                recipient_list='收件人列表',
                html_message='html不轉(zhuǎn)義正文,**該參數(shù)為關(guān)鍵字參數(shù)**')
    return HttpResponse('ok')

5.配置應(yīng)用url
url(r'^send/$',views.send),
6.測(cè)試調(diào)用發(fā)送函數(shù)
http://127.0.0.1:8000/send/

django中celery 異步發(fā)送郵件

1.安裝celery和django-celery
pip install celery==3.1.25
pip install django-celery==3.1.17
注意:celery和djcelery的大版本需要一樣, 不然會(huì)沖突
2.在應(yīng)用booktest的views.py文件中創(chuàng)建def sayhello(request)函數(shù)

import time
...
def sayhello(request):
    print('hello ...')
    time.sleep(2)
    print('world ...')
    return HttpResponse("hello world")

3.在應(yīng)用booktesturls.py中配置
url(r'^sayhello$',views.sayhello),
4.啟動(dòng)服務(wù)器,訪問網(wǎng)址
http://127.0.0.1:8000/sayhello/
5.兩次輸出之間等待一段時(shí)間才會(huì)返回結(jié)果,終端中可以看到等待過程
6.在項(xiàng)目的settings.py中注冊(cè)djcelery應(yīng)用

INSTALLED_APPS = (
  ...
  'djcelery',
}

7.在項(xiàng)目settings.py文件中配置代理和任務(wù)模塊秸脱。

import djcelery
djcelery.setup_loader()
BROKER_URL = 'redis://127.0.0.1:6379/2'

8.在應(yīng)用booktest目錄下創(chuàng)建tasks.py文件

import time
from celery import task

@task #一定要裝飾之后才能正常使用
def sayhello():
    print('hello ...')
    time.sleep(2)
    print('world ...')

9.將應(yīng)用booktest的views.py文件敷存,修改sayhello視圖如下

from booktest import tasks
...
def sayhello(request):
    # print('hello ...')
    # time.sleep(2)
    # print('world ...')
    tasks.sayhello.delay()
    return HttpResponse("hello world")

10.執(zhí)行遷移生成celery需要的數(shù)據(jù)表。
python manage.py migrate
11.啟動(dòng)redis
redis-server +配置文件路徑
12.django項(xiàng)目啟動(dòng)worker
python manage.py celery worker --loglevel=info
注意:需要在manage.py目錄使用該命令

13.打開新終端痴脾,進(jìn)入虛擬環(huán)境纪挎,啟動(dòng)服務(wù)器期贫,刷新瀏覽器。 在舊終端中兩個(gè)輸出間仍有時(shí)間間隔异袄。注意兩個(gè)終端中的時(shí)間通砍,服務(wù)器的響應(yīng)是立即返回的。
14.打開應(yīng)用booktest/task.py文件烤蜕,修改為發(fā)送郵件的代碼封孙,就可以實(shí)現(xiàn)無(wú)阻塞發(fā)送郵件。

from django.conf import settings
from django.core.mail import send_mail
from celery import task

@task
def sayhello():
    msg='<a href="網(wǎng)站" target="_blank">點(diǎn)擊激活</a>'
    send_mail('注冊(cè)激活','',settings.EMAIL_FROM,
              ['郵箱'],
              html_message=msg)

django內(nèi)置login/logout函數(shù)使用

1.login(request, user)
從視圖中登入一個(gè)用戶讽营,請(qǐng)使用login()虎忌。它接受一個(gè)HttpRequest對(duì)象和一個(gè)User對(duì)象。login()使用Django的session框架來(lái)將用戶的ID保存在session中橱鹏。

注意任何在匿名會(huì)話中設(shè)置的數(shù)據(jù)都會(huì)在用戶登入后的會(huì)話中都會(huì)記住呐籽。

下面的示例向你演示如何使用authenticate() 和login():

from django.contrib.auth import authenticate, login

def my_view(request):
    username = request.POST['username']
    password = request.POST['password']
    user = authenticate(username=username, password=password)
    if user is not None:
        if user.is_active:
            login(request, user)
            # Redirect to a success page.
        else:
            # Return a 'disabled account' error message
            ...
    else:
        # Return an 'invalid login' error message.
        ...

先調(diào)用authenticate()認(rèn)證Users:
使用authenticate()锋勺,認(rèn)證一組給定的用戶名和密碼。它接收關(guān)鍵字參數(shù)形式的憑證狡蝶,使用默認(rèn)配置時(shí)參數(shù)是username和password庶橱,如果密碼能夠匹配給定的用戶名,它將返回一個(gè)User對(duì)象贪惹。如果密碼無(wú)效苏章,authenticate()返回None.

from django.contrib.auth import authenticate
user = authenticate(username='john', password='secret')
if user is not None:
    # the password verified for the user
    if user.is_active:
        print("User is valid, active and authenticated")
    else:
        print("The password is valid, but the account has been disabled!")
else:
    # the authentication system was unable to verify the username and password
    print("The username and password were incorrect.")

當(dāng)你是手工登入一個(gè)用戶時(shí),你必須在調(diào)用login()之前通過authenticate()成功地認(rèn)證該用戶奏瞬。authenticate()在用戶上設(shè)置一個(gè)屬性枫绅,注意哪個(gè)認(rèn)證后端成功驗(yàn)證了該用戶(有關(guān)詳細(xì)信息,請(qǐng)參閱后端文檔)硼端,以及此信息以后在登錄過程中需要并淋。如果你試圖登入一個(gè)直接從數(shù)據(jù)庫(kù)中取出的用戶,將會(huì)拋出一個(gè)錯(cuò)誤珍昨。

2.logout()
若要登出一個(gè)已經(jīng)通過django.contrib.auth.login()登入的用戶县耽,在你的視圖中使用django.contrib.auth.logout()。 它接收一個(gè)HttpRequest對(duì)象且沒有返回值.

from django.contrib.auth import logout
def logout_view(request):
    logout(request)
    # Redirect to a success page.

注意: 即使用戶沒有登入镣典,logout()也不會(huì)拋出任何錯(cuò)誤兔毙。
當(dāng)你調(diào)用logout()時(shí),當(dāng)前請(qǐng)求的會(huì)話數(shù)據(jù)將被完全清除。所有存在的數(shù)據(jù)都將清除兄春。
3.在模板中判斷用戶是否登錄
request對(duì)象中有一個(gè)user屬性, request.user
如果用戶已登錄:
request.user是一個(gè)認(rèn)證用戶模型類(User)的對(duì)象,包含用戶的信息,
可以直接使用user.username user.email等等
如果用戶未登錄:
request.user是一個(gè)匿名用戶類(AnonymousUser)的對(duì)象
user.is_authenticated:
已登錄的User類的user.is_authenticated這個(gè)方法永遠(yuǎn)返回的是True
未登錄的AnonymousUser類user.is_authenticated這個(gè)方法永遠(yuǎn)返回False
所以在模板文件中可以直接使用一個(gè)模板變量user澎剥,實(shí)際上就是request.user

django 內(nèi)置login_required裝飾器的使用(只允許登錄的用戶訪問?)

  1. URLconf中裝飾
from django.contrib.auth.decorators import login_required, permission_required
from django.views.generic import TemplateView
 
from .views import VoteView
 
urlpatterns = [
 url(r'^about/', login_required(TemplateView.as_view(template_name="secret.html"))),
 url(r'^vote/', permission_required('polls.can_vote')(VoteView.as_view())),
]
  1. 裝飾基于函數(shù)的視圖
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
 
@login_required
def my_view(request):
 if request.method == 'GET':
  # <view logic>
  return HttpResponse('result')
  1. 裝飾類的視圖:需要導(dǎo)入method_decorator
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView
 
class ProtectedView(TemplateView):
 template_name = 'secret.html'
 
 @method_decorator(login_required)
 def dispatch(self, *args, **kwargs):
  return super(ProtectedView, self).dispatch(*args, **kwargs)
  1. 裝飾通過Mixin類繼承來(lái)實(shí)現(xiàn)
from django.contrib.auth.decorators import login_required
 
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.views.generic import View
 
from .forms import MyForm
 
class LoginRequiredMixin(object):
 @classmethod
 def as_view(cls, **initkwargs):
  view = super(LoginRequiredMixin, cls).as_view(**initkwargs)
  return login_required(view)
 
class MyFormView(LoginRequiredMixin, View):
 form_class = MyForm
 initial = {'key': 'value'}
 template_name = 'form_template.html'
 
 def get(self, request, *args, **kwargs):
  form = self.form_class(initial=self.initial)
  return render(request, self.template_name, {'form': form})
  
 def post(self, request, *args, **kwargs):
  # code here

設(shè)置Django框架的緩存, 將session存儲(chǔ)到redis

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        # 設(shè)置django緩存的數(shù)據(jù)保存在redis數(shù)據(jù)庫(kù)中
        "LOCATION": "redis://127.0.0.1:6379/2",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}
# Django的session存儲(chǔ)設(shè)置到redis
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
# 設(shè)置session信息存儲(chǔ)在CACHES配置項(xiàng)default對(duì)應(yīng)的redis中
SESSION_CACHE_ALIAS = "default"

------------------分割線-------------
直接使用celery發(fā)送郵件的方式


0.準(zhǔn)備工作
-0.1創(chuàng)建deme項(xiàng)目
django-admin start-project demo
進(jìn)入項(xiàng)目目錄: cd demo
-0.2 創(chuàng)建應(yīng)用user
python manage.py startapp user

1.創(chuàng)建一個(gè)目錄存放tasks.py

image.png

tasks.py文件

# 導(dǎo)入Celery類
from celery import Celery
from django.core.mail import send_mail

# 初始化django運(yùn)行所以來(lái)的環(huán)境變量
# 這兩行代碼在啟動(dòng)worker一端打開
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dailyfresh.settings") #
# 或者這樣設(shè)置,兩個(gè)都可以
# os.environ['DJANGO_SETTINGS_MODULE'] = 'dailyfresh.settings'

#創(chuàng)建celery類的對(duì)象
app = Celery('celery_tasks.tasks',broker='redis://127.0.0.1:6379/7')

# 封裝任務(wù)函數(shù)
@app.task
def my_task(subject, message, from_email, receiver, html_message):
    # 模擬send_mail發(fā)送郵件時(shí)間
    import time
    time.sleep(5)
    send_mail(subject, message, from_email, receiver, html_message=html_message)

2.在views.py視圖文件中調(diào)用任務(wù)執(zhí)行

def send(request):
  send_mail(subject='郵件標(biāo)題',
                     message='郵件html會(huì)轉(zhuǎn)義正文',
                     from_email='發(fā)件人郵箱',
                     recipient_list='收件人郵箱列表',
                     html_message='html不轉(zhuǎn)義正文')

  from celery_tasks import tasks # 導(dǎo)入tasks
  tasks.my_task.delay(subject, message, from_email, receiver, html_message=html_message)

3.配置應(yīng)用urls.py(可以調(diào)用到視圖函數(shù)的urls文件)

from django.conf.urls import url
from user import views
urlpatterns = [
    # url(r'^$', views.send, name='send'), 
]

4.進(jìn)入項(xiàng)目目錄再啟動(dòng)celery worker
celery -A celery_tasks.tasks worker -l info

5.啟動(dòng)redis
redis-server 加配置文件

6.打開瀏覽器訪問網(wǎng)址
127.0.0.1:8000

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市赶舆,隨后出現(xiàn)的幾起案子哑姚,更是在濱河造成了極大的恐慌,老刑警劉巖芜茵,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蜻懦,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡夕晓,警方通過查閱死者的電腦和手機(jī)宛乃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蒸辆,“玉大人征炼,你說我怎么就攤上這事」保” “怎么了谆奥?”我有些...
    開封第一講書人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)拂玻。 經(jīng)常有香客問我酸些,道長(zhǎng)宰译,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任魄懂,我火速辦了婚禮沿侈,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘市栗。我一直安慰自己缀拭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開白布填帽。 她就那樣靜靜地躺著蛛淋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪篡腌。 梳的紋絲不亂的頭發(fā)上褐荷,一...
    開封第一講書人閱讀 51,115評(píng)論 1 296
  • 那天,我揣著相機(jī)與錄音嘹悼,去河邊找鬼叛甫。 笑死,一個(gè)胖子當(dāng)著我的面吹牛绘迁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播卒密,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼缀台,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了哮奇?” 一聲冷哼從身側(cè)響起膛腐,我...
    開封第一講書人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鼎俘,沒想到半個(gè)月后哲身,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贸伐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年勘天,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捉邢。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡脯丝,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出伏伐,到底是詐尸還是另有隱情宠进,我是刑警寧澤,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布藐翎,位于F島的核電站材蹬,受9級(jí)特大地震影響实幕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜堤器,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一昆庇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吼旧,春花似錦凰锡、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至员串,卻和暖如春勇哗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背寸齐。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工欲诺, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人渺鹦。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓扰法,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親毅厚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子塞颁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容