項(xiàng)目開發(fā)中視圖處理一般流程:
1.接收參數(shù)
2.參數(shù)校驗(yàn)(后端校驗(yàn))
3.處理業(yè)務(wù)邏輯
4.返回應(yīng)答
- 為了將項(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裝飾器的使用(只允許登錄的用戶訪問?)
- 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())),
]
- 裝飾基于函數(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')
- 裝飾類的視圖:需要導(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)
- 裝飾通過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
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