![Django 3 Web應(yīng)用開發(fā)實(shí)戰(zhàn)(下篇)_第1頁(yè)](http://file4.renrendoc.com/view/24008f79b773916304ac03b13ab79dbe/24008f79b773916304ac03b13ab79dbe1.gif)
![Django 3 Web應(yīng)用開發(fā)實(shí)戰(zhàn)(下篇)_第2頁(yè)](http://file4.renrendoc.com/view/24008f79b773916304ac03b13ab79dbe/24008f79b773916304ac03b13ab79dbe2.gif)
![Django 3 Web應(yīng)用開發(fā)實(shí)戰(zhàn)(下篇)_第3頁(yè)](http://file4.renrendoc.com/view/24008f79b773916304ac03b13ab79dbe/24008f79b773916304ac03b13ab79dbe3.gif)
![Django 3 Web應(yīng)用開發(fā)實(shí)戰(zhàn)(下篇)_第4頁(yè)](http://file4.renrendoc.com/view/24008f79b773916304ac03b13ab79dbe/24008f79b773916304ac03b13ab79dbe4.gif)
![Django 3 Web應(yīng)用開發(fā)實(shí)戰(zhàn)(下篇)_第5頁(yè)](http://file4.renrendoc.com/view/24008f79b773916304ac03b13ab79dbe/24008f79b773916304ac03b13ab79dbe5.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
Django3Web應(yīng)用開發(fā)實(shí)戰(zhàn)(下篇)目錄\h第10章Auth認(rèn)證系統(tǒng)\h10.1內(nèi)置User實(shí)現(xiàn)用戶管理\h10.2發(fā)送郵件實(shí)現(xiàn)密碼找回\h10.3模型User的擴(kuò)展與使用\h10.4權(quán)限的設(shè)置與使用\h10.5自定義用戶權(quán)限\h10.6設(shè)置網(wǎng)頁(yè)的訪問權(quán)限\h10.7用戶組的設(shè)置與使用\h第11章常用的Web應(yīng)用程序\h11.1會(huì)話控制\h11.1.1會(huì)話的配置與操作\h11.1.2使用會(huì)話實(shí)現(xiàn)商品搶購(gòu)\h11.2緩存機(jī)制\h11.2.1緩存的類型與配置\h11.2.2緩存的使用\h11.3CSRF防護(hù)\h11.4消息框架\h11.4.1源碼分析消息框架\h11.4.2消息框架的使用\h11.5分頁(yè)功能\h11.5.1源碼分析分頁(yè)功能\h11.5.2分頁(yè)功能的使用\h11.6國(guó)際化和本地化\h11.6.1環(huán)境搭建與配置\h11.6.2設(shè)置國(guó)際化\h11.6.3設(shè)置本地化\h11.7單元測(cè)試\h11.7.1定義測(cè)試類\h11.7.2運(yùn)行測(cè)試用例\h11.8自定義中間件\h11.8.1中間件的定義過程\h11.8.2中間件實(shí)現(xiàn)Cookie反爬蟲\h11.9異步編程\h11.9.1使用多線程\h11.9.2啟用ASGI服務(wù)\h11.9.3異步視圖\h11.9.4異步與同步的轉(zhuǎn)換\h11.10信號(hào)機(jī)制\h11.10.1內(nèi)置信號(hào)\h11.10.2自定義信號(hào)\h11.10.3訂單創(chuàng)建與取消\h第12章第三方功能應(yīng)用\h12.1DjangoRestFramework框架\h12.1.1DRF的安裝與配置\h12.1.2序列化類Serializer\h12.1.3模型序列化類ModelSerializer\h12.1.4序列化的嵌套使用\h12.2驗(yàn)證碼生成與使用\h12.2.1DjangoSimpleCaptcha的安裝與配置\h12.2.2使用驗(yàn)證碼實(shí)現(xiàn)用戶登錄\h12.3站內(nèi)搜索引擎\h12.3.1DjangoHaystack的安裝與配置\h12.3.2使用搜索引擎實(shí)現(xiàn)產(chǎn)品搜索\h12.4第三方網(wǎng)站實(shí)現(xiàn)用戶注冊(cè)\h12.4.1Social-Auth-App-Django的安裝與配置\h12.4.2微博賬號(hào)實(shí)現(xiàn)用戶注冊(cè)\h12.5異步任務(wù)和定時(shí)任務(wù)\h12.5.1Celery的安裝與配置\h12.5.2異步任務(wù)\h12.5.3定時(shí)任務(wù)\h12.6即時(shí)通信——在線聊天\h12.6.1Channels的安裝與配置\h12.6.2Web在線聊天功能\h第13章信息反饋平臺(tái)的設(shè)計(jì)與實(shí)現(xiàn)\h13.1項(xiàng)目設(shè)計(jì)與配置\h13.1.1項(xiàng)目架構(gòu)設(shè)計(jì)\h13.1.2MySQL搭建與配置\h13.1.3功能配置\h13.1.4數(shù)據(jù)庫(kù)架構(gòu)設(shè)計(jì)\h13.2程序功能開發(fā)\h13.2.1路由與視圖函數(shù)\h13.2.2使用Jinja2編寫模板文件\h13.2.3Admin后臺(tái)系統(tǒng)\h13.3測(cè)試與運(yùn)行\(zhòng)h13.3.1編寫單元測(cè)試\h13.3.2運(yùn)行與上線\h第14章個(gè)人博客系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)\h14.1項(xiàng)目設(shè)計(jì)與配置\h14.1.1項(xiàng)目架構(gòu)設(shè)計(jì)\h14.1.2功能配置\h14.1.3數(shù)據(jù)表架構(gòu)設(shè)計(jì)\h14.1.4定義路由列表\h14.1.5編寫共用模板\h14.2注冊(cè)與登錄\h14.3博主資料信息\h14.4圖片墻功能\h14.5留言板功能\h14.6文章列表\h14.7文章正文內(nèi)容\h14.8Admin后臺(tái)系統(tǒng)\h14.8.1模型的數(shù)據(jù)管理\h14.8.2自定義Admin的登錄頁(yè)面\h14.8.3DjangoCKEditor生成文章編輯器\h14.9測(cè)試與部署\h14.9.1測(cè)試業(yè)務(wù)邏輯\h14.9.2上線部署\h第15章音樂網(wǎng)站平臺(tái)的設(shè)計(jì)與實(shí)現(xiàn)\h15.1項(xiàng)目設(shè)計(jì)與配置\h15.1.1項(xiàng)目架構(gòu)設(shè)計(jì)\h15.1.2功能配置\h15.1.3數(shù)據(jù)表架構(gòu)設(shè)計(jì)\h15.1.4定義路由列表\h15.1.5編寫共用模板\h15.2網(wǎng)站首頁(yè)\h15.3歌曲排行榜\h15.4歌曲搜索\h15.5歌曲播放與下載\h15.6歌曲點(diǎn)評(píng)\h15.7注冊(cè)與登錄\h15.8用戶中心\h15.9Admin后臺(tái)系統(tǒng)\h15.10自定義異常頁(yè)面\h15.11部署與運(yùn)行\(zhòng)h15.11.1上線部署\h15.11.2網(wǎng)站試運(yùn)行\(zhòng)h第16章基于前后端分離與微服務(wù)架構(gòu)的網(wǎng)站開發(fā)\h16.1Vue框架\h16.1.1Vue開發(fā)產(chǎn)品信息頁(yè)\h16.1.2Vue發(fā)送AJAX請(qǐng)求\h16.2Django開發(fā)API接口\h16.2.1簡(jiǎn)化Django內(nèi)置功能\h16.2.2設(shè)置跨域訪問\h16.2.3使用路由視圖開發(fā)API接口\h16.2.4DRF框架開發(fā)API接口\h16.3微服務(wù)架構(gòu)\h16.3.1微服務(wù)實(shí)現(xiàn)原理\h16.3.2功能拆分\h16.3.3設(shè)計(jì)API網(wǎng)關(guān)\h16.3.4調(diào)試與運(yùn)行\(zhòng)h16.4JWT認(rèn)證\h16.4.1認(rèn)識(shí)JWT\h16.4.2DRF的JWT\h16.5微服務(wù)注冊(cè)與發(fā)現(xiàn)\h16.5.1常用的服務(wù)注冊(cè)與發(fā)現(xiàn)框架\h16.5.2Consul的安裝與接口\h16.5.3Django與Consul的交互\h16.5.4服務(wù)的運(yùn)行與部署\h16.5.5服務(wù)的負(fù)載均衡\h第17章Django項(xiàng)目上線部署\h17.1基于Windows部署Django\h17.1.1安裝IIS服務(wù)器\h17.1.2創(chuàng)建項(xiàng)目站點(diǎn)\h17.1.3配置靜態(tài)資源\h17.2基于Linux部署Django\h17.2.1安裝Linux虛擬機(jī)\h17.2.2安裝Python3\h17.2.3部署uWSGI服務(wù)器\h17.2.4安裝Nginx部署項(xiàng)目第10章Auth認(rèn)證系統(tǒng)Django除了內(nèi)置的Admin后臺(tái)系統(tǒng)之外,還內(nèi)置了Auth認(rèn)證系統(tǒng)。整個(gè)Auth認(rèn)證系統(tǒng)可分為三大部分:用戶信息、用戶權(quán)限和用戶組,在數(shù)據(jù)庫(kù)中分別對(duì)應(yīng)數(shù)據(jù)表auth_user、auth_permission和auth_group。10.1內(nèi)置User實(shí)現(xiàn)用戶管理用戶管理是網(wǎng)站必備的功能之一,Django內(nèi)置的Auth認(rèn)證系統(tǒng)不僅功能完善,而且具有靈活的擴(kuò)展性,可以滿足多方面的開發(fā)需求。創(chuàng)建項(xiàng)目時(shí),Django已默認(rèn)使用內(nèi)置Auth認(rèn)證系統(tǒng),在settings.py的INSTALLED_APPS、MIDDLEWARE和AUTH_PASSWORD_VALIDATORS中都能看到相關(guān)的配置信息。本節(jié)將使用內(nèi)置的Auth認(rèn)證系統(tǒng)實(shí)現(xiàn)用戶注冊(cè)、登錄、修改密碼和注銷功能。在D盤下創(chuàng)建新的MyDjango項(xiàng)目,添加項(xiàng)目應(yīng)用user,并新建templates和static文件夾。在templates中放置模板文件user.html,在static中放置模板文件user.html所需的JS和CSS文件。項(xiàng)目的目錄結(jié)構(gòu)如圖10-1所示。圖10-1目錄結(jié)構(gòu)打開MyDjango的配置文件settings.py,將項(xiàng)目應(yīng)用user、模板文件夾templates和靜態(tài)資源文件夾static添加到Django的運(yùn)行環(huán)境,配置信息如下:完成MyDjango的基本配置后,在PyCharm的Terminal下執(zhí)行數(shù)據(jù)遷移指令,項(xiàng)目?jī)?nèi)置的數(shù)據(jù)表創(chuàng)建在MyDjango的db.sqlite3數(shù)據(jù)庫(kù)文件中。打開并查看db.sqlite3數(shù)據(jù)庫(kù)文件的數(shù)據(jù)表信息,如圖10-2所示。圖10-2數(shù)據(jù)表信息項(xiàng)目環(huán)境搭建成功后,在項(xiàng)目應(yīng)用user中創(chuàng)建urls.py文件,并分別在MyDjango文件夾的urls.py和user的urls.py中定義用戶注冊(cè)、登錄、修改密碼和注銷的路由信息,代碼如下:#MyDjango的urls.py
fromdjango.urlsimportpath,include
urlpatterns=[
path('',include(('user.urls','user'),namespace='user')),
]
#user的urls.py
fromdjango.urlsimportpath
from.viewsimport*
urlpatterns=[
path('login.html',loginView,name='login'),
path('register.html',registerView,name='register'),
path('setps.html',setpsView,name='setps'),
path('logout.html',logoutView,name='logout'),
]
項(xiàng)目應(yīng)用user定義了4條路由信息,分別代表用戶注冊(cè)、登錄、修改密碼和注銷,而4條路由所對(duì)應(yīng)的網(wǎng)頁(yè)信息都由模板文件user.html生成,因此在模板文件user.html中編寫以下代碼:完成項(xiàng)目的功能配置、路由設(shè)置和模板代碼編寫后,最后在user的views.py里定義視圖函數(shù)。首先定義視圖函數(shù)registerView,實(shí)現(xiàn)用戶注冊(cè)功能,代碼如下:視圖函數(shù)registerView對(duì)用戶請(qǐng)求進(jìn)行判斷分析,如果當(dāng)前請(qǐng)求為GET請(qǐng)求,就調(diào)用模板文件user.html生成用戶注冊(cè)頁(yè)面;如果當(dāng)前請(qǐng)求為POST請(qǐng)求,就由內(nèi)置的Auth認(rèn)證系統(tǒng)執(zhí)行用戶注冊(cè)過程,具體說明如下:(1)當(dāng)用戶在注冊(cè)頁(yè)面輸入賬號(hào)和密碼,并單擊“確定”按鈕后,程序?qū)⒈韱螖?shù)據(jù)提交到函數(shù)registerView中進(jìn)行處理。(2)函數(shù)registerView首先獲取表單的數(shù)據(jù)內(nèi)容,根據(jù)獲取的數(shù)據(jù)來判斷Django內(nèi)置模型User是否存在相關(guān)的用戶信息。(3)如果用戶存在,就直接返回注冊(cè)頁(yè)面并提示用戶已存在。(4)如果用戶不存在,程序就使用內(nèi)置函數(shù)create_user對(duì)模型User進(jìn)行用戶創(chuàng)建,函數(shù)create_user是模型User特有的函數(shù),該函數(shù)創(chuàng)建并保存一個(gè)is_active=True的User對(duì)象。其中,函數(shù)參數(shù)username不能為空,否則拋出ValueError異常;而模型User的其他字段可作為函數(shù)create_user的可選參數(shù),模型User的字段可在數(shù)據(jù)表auth_user中查看,如email、first_name和password等。如果沒有設(shè)置參數(shù)password,模型User就調(diào)用set_unusable_password()為當(dāng)前用戶創(chuàng)建一個(gè)隨機(jī)密碼。Django的內(nèi)置模型User一共定義了11個(gè)字段,各個(gè)字段的含義說明如表10-1所示。表10-1User模型各個(gè)字段的說明運(yùn)行MyDjango項(xiàng)目,在瀏覽器上訪問:8000/register.html,在用戶注冊(cè)表單中填寫賬號(hào)密碼,單擊“確定”按鈕即可完成用戶注冊(cè)。打開數(shù)據(jù)表auth_user就能看到新建的用戶信息,如圖10-3所示。圖10-3數(shù)據(jù)表auth_user下一步實(shí)現(xiàn)用戶登錄過程,同時(shí)也能驗(yàn)證視圖函數(shù)registerView實(shí)現(xiàn)的用戶注冊(cè)功能是否正常。我們?cè)趗ser的views.py中定義視圖函數(shù)loginView,函數(shù)代碼如下:視圖函數(shù)loginView與registerView的實(shí)現(xiàn)過程有相似之處,它也是對(duì)用戶請(qǐng)求進(jìn)行判斷分析,如果當(dāng)前請(qǐng)求為GET請(qǐng)求,就調(diào)用模板文件user.html生成用戶登錄頁(yè)面;如果當(dāng)前請(qǐng)求為POST請(qǐng)求,就由內(nèi)置的Auth認(rèn)證系統(tǒng)執(zhí)行用戶登錄過程,具體說明如下:(1)當(dāng)函數(shù)loginView收到POST請(qǐng)求并獲取表單的數(shù)據(jù)后,根據(jù)表單數(shù)據(jù)判斷用戶是否存在。如果用戶存在,就對(duì)用戶賬號(hào)和密碼進(jìn)行驗(yàn)證處理,由內(nèi)置函數(shù)authenticate完成驗(yàn)證過程,若驗(yàn)證成功,則返回模型Uesr的用戶對(duì)象user,否則返回None。(2)從用戶對(duì)象user的is_active字段來判斷當(dāng)前用戶狀態(tài)是否被激活,如果字段is_active的值為1,就說明當(dāng)前用戶處于已激活狀態(tài),可執(zhí)行用戶登錄。(3)執(zhí)行用戶登錄,由內(nèi)置函數(shù)login完成登錄過程。函數(shù)login接收兩個(gè)參數(shù),第一個(gè)是request對(duì)象,來自視圖函數(shù)的參數(shù)request;第二個(gè)是user對(duì)象,來自函數(shù)authenticate返回的對(duì)象user。運(yùn)行MyDjango項(xiàng)目,在瀏覽器上訪問:8000/login.html,在用戶登錄表單中填寫新建的admin用戶信息,單擊“確定”按鈕即可完成用戶登錄。我們可以在數(shù)據(jù)表auth_user中查看admin用戶的登錄時(shí)間來驗(yàn)證登錄是否成功,如圖10-4所示。圖10-4數(shù)據(jù)表auth_user密碼修改頁(yè)面是根據(jù)已有的用戶信息進(jìn)行密碼修改。我們?cè)趗ser的views.py中定義視圖函數(shù)setpsView,函數(shù)代碼如下:密碼修改頁(yè)面相比注冊(cè)和登錄頁(yè)面多出了一個(gè)文本輸入框,該文本輸入框由模板上下文password2控制顯示。當(dāng)password2為True時(shí),文本輸入框?qū)@示到頁(yè)面上,如圖10-5所示。圖10-5修改密碼頁(yè)面視圖函數(shù)setpsView的處理邏輯與用戶注冊(cè)、登錄大致相同,函數(shù)處理邏輯說明如下:(1)當(dāng)函數(shù)setpsView收到POST請(qǐng)求后,程序獲取表單的數(shù)據(jù)內(nèi)容,然后在表單數(shù)據(jù)中查找模型User的用戶信息。(2)如果用戶存在,就由內(nèi)置函數(shù)authenticate驗(yàn)證用戶的賬號(hào)和密碼是否正確。若驗(yàn)證成功,則返回對(duì)象user,再由對(duì)象user使用內(nèi)置函數(shù)set_password修改當(dāng)前用戶的密碼,最后保存修改后的對(duì)象user,從而實(shí)現(xiàn)密碼修改。(3)如果用戶不存在,就直接返回密碼修改頁(yè)面并提示用戶不存在。密碼修改主要由內(nèi)置函數(shù)set_password實(shí)現(xiàn),而函數(shù)set_password是在內(nèi)置函數(shù)make_password的基礎(chǔ)上進(jìn)行封裝而來的。Django默認(rèn)使用pbkdf2_sha256方式存儲(chǔ)和管理用戶密碼,而內(nèi)置函數(shù)make_password用于實(shí)現(xiàn)用戶密碼的加密處理,并且該函數(shù)可以脫離Auth認(rèn)證系統(tǒng)單獨(dú)使用,比如對(duì)某些特殊數(shù)據(jù)進(jìn)行加密處理等。在user的views.py中定義視圖函數(shù)setpsView2,它使用函數(shù)make_password實(shí)現(xiàn)密碼修改,代碼如下:視圖函數(shù)setpsView2與setpsView的處理邏輯相同,只不過兩者修改密碼的方法有所不同。除了內(nèi)置函數(shù)make_password之外,還有內(nèi)置函數(shù)check_password,該函數(shù)是對(duì)加密前的密碼與加密后的密碼進(jìn)行驗(yàn)證匹配,判斷兩者是否為同一個(gè)密碼。在PyCharm的Terminal中開啟Django的Shell模式,函數(shù)make_password和check_password的使用方法如下:D:\MyDjango>pythonmanage.pyshell
>>>fromdjango.contrib.auth.hashersimportmake_password
>>>fromdjango.contrib.auth.hashersimportcheck_password
>>>ps="123456"
>>>dj_ps=make_password(ps,None,'pbkdf2_sha256')
>>>ps_bool=check_password(ps,dj_ps)
>>>ps_bool
True
用戶注銷是Auth認(rèn)證系統(tǒng)較為簡(jiǎn)單的功能,只需調(diào)用內(nèi)置函數(shù)logout即可實(shí)現(xiàn)。函數(shù)logout的參數(shù)request代表當(dāng)前用戶的請(qǐng)求對(duì)象,來自于視圖函數(shù)的參數(shù)request。因此,視圖函數(shù)logoutView的代碼如下:#用戶注銷,退出登錄
deflogoutView(request):
logout(request)
returnHttpResponse('注銷成功')
綜上所述,整個(gè)MyDjango項(xiàng)目定義了4條路由信息,分別實(shí)現(xiàn)用戶注冊(cè)、登錄、修改密碼和注銷功能。由Auth認(rèn)證系統(tǒng)的內(nèi)置模型User實(shí)現(xiàn)用戶信息管理,開發(fā)者只需調(diào)用內(nèi)置函數(shù)即可實(shí)現(xiàn)功能開發(fā)。10.2發(fā)送郵件實(shí)現(xiàn)密碼找回在10.1節(jié)中,密碼修改是在用戶知道密碼的情況下實(shí)現(xiàn)的,而在日常應(yīng)用中,還有一種是在用戶忘記密碼的情況下實(shí)現(xiàn)密碼修改,也稱為密碼找回。密碼找回首先需要對(duì)用戶賬號(hào)進(jìn)行驗(yàn)證,確認(rèn)該賬號(hào)是當(dāng)前用戶所擁有的,驗(yàn)證成功才能為用戶重置密碼。用戶驗(yàn)證方式主要有手機(jī)驗(yàn)證碼和郵件驗(yàn)證碼,因此本節(jié)使用Django內(nèi)置的郵件功能發(fā)送驗(yàn)證碼,從而實(shí)現(xiàn)密碼找回功能。在實(shí)現(xiàn)郵件發(fā)送功能之前,我們需要對(duì)郵箱進(jìn)行相關(guān)配置,以QQ郵箱為例,在QQ郵箱的設(shè)置中找到賬戶設(shè)置,在賬戶設(shè)置中找到POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服務(wù),然后開啟POP3/SMTP服務(wù),如圖10-6所示。圖10-6開啟POP3/SMTP服務(wù)開啟服務(wù)成功后,QQ郵箱會(huì)返回一個(gè)客戶端授權(quán)密碼,該密碼是用于登錄第三方郵件客戶端的專用密碼,切記保存授權(quán)密碼,該密碼在開發(fā)過程中需要使用。如果QQ開啟了登錄保護(hù),就必須取消登錄保護(hù),否則Django無法使用POP3/SMTP服務(wù)發(fā)送郵件驗(yàn)證碼。下一步在Django里使用POP3/SMTP服務(wù)發(fā)送郵件驗(yàn)證碼,以10.1節(jié)的MyDjango為例,在配置文件settings.py中設(shè)置郵件配置信息,配置信息如下:#郵件配置信息
EMAIL_USE_SSL=True
#郵件服務(wù)器,如果是163,就改成
EMAIL_HOST=''
#郵件服務(wù)器端口
EMAIL_PORT=465
#發(fā)送郵件的賬號(hào)
EMAIL_HOST_USER='185231027@'
#SMTP服務(wù)密碼
EMAIL_HOST_PASSWORD='odnwdcwsphzi'
DEFAULT_FROM_EMAIL=EMAIL_HOST_USER
郵件配置一共設(shè)置6個(gè)配置屬性,這些屬性是配置郵件發(fā)送方的服務(wù)器信息,配置屬性的值是由郵件服務(wù)器決定的。每個(gè)配置屬性的作用說明如下:●EMAIL_USE_SSL:Django與郵件服務(wù)器的連接方式是否設(shè)為SSL模式。●EMAIL_HOST:設(shè)置服務(wù)器類型,QQ郵箱分為SMTP服務(wù)器和POP3服務(wù)器?!馝MAIL_PORT:設(shè)置服務(wù)器端口號(hào),若使用SMTP服務(wù)器,則端口應(yīng)為465或587?!馝MAIL_HOST_USER:發(fā)送郵件的賬號(hào),該賬號(hào)必須開啟POP3/SMTP服務(wù)?!馝MAIL_HOST_PASSWORD:客戶端授權(quán)密碼,即圖10-6開啟服務(wù)后所獲得的授權(quán)碼?!馜EFAULT_FROM_EMAIL:設(shè)置默認(rèn)發(fā)送郵件的賬號(hào)。完成郵件相關(guān)配置后,在MyDjango的urls.py和user的urls.py中定義路由信息,分別設(shè)置Admin后臺(tái)系統(tǒng)的路由和定義密碼找回的路由,代碼如下:#MyDjango的urls.py
fromdjango.urlsimportpath,include
fromdjango.contribimportadmin
urlpatterns=[
path('admin/',admin.site.urls),
path('',include(('user.urls','user'),namespace='user')),
]
#user的urls.py
fromdjango.urlsimportpath
from.viewsimport*
urlpatterns=[
path('',findpsView,name='findps'),
]
設(shè)置Admin后臺(tái)系統(tǒng)的路由可以驗(yàn)證用戶密碼修改后是否能正常登錄Admin后臺(tái)系統(tǒng)。接著修改模板文件user.html的用戶表單,代碼如下:模板文件user.html設(shè)置了4個(gè)模板上下文,分別為password、VCodeInfo、tips和button,每個(gè)上下文的說明如下:●password控制密碼文本框是否顯示在網(wǎng)頁(yè)上,數(shù)據(jù)類型為布爾型。●VCodeInfo控制驗(yàn)證碼文本框是否顯示在網(wǎng)頁(yè)上,數(shù)據(jù)類型為布爾型?!駎ips是根據(jù)用戶操作和賬號(hào)驗(yàn)證設(shè)置的信息提示,信息內(nèi)容分別為:“驗(yàn)證碼已發(fā)送”“用戶XXX不存在”“密碼已重置”和“驗(yàn)證碼錯(cuò)誤,請(qǐng)重新獲取”?!馼utton可以改變表單提交按鈕的文本內(nèi)容,內(nèi)容分別為:“獲取驗(yàn)證碼”和“重置密碼”。最后在user的views.py中定義視圖函數(shù)findpsView,該函數(shù)實(shí)現(xiàn)3個(gè)功能:發(fā)送郵件驗(yàn)證碼、驗(yàn)證郵件驗(yàn)證碼和修改密碼,具體代碼如下:由于視圖函數(shù)findpsView實(shí)現(xiàn)3個(gè)不同的功能,因此從功能使用的角度分析視圖函數(shù)findpsView。運(yùn)行MyDjango并在瀏覽器上訪問:8000,視圖函數(shù)findpsView觸發(fā)GET請(qǐng)求,調(diào)用模板文件user.html生成網(wǎng)頁(yè)表單,在網(wǎng)頁(yè)表單上輸入用戶賬號(hào)admin并單擊“獲取驗(yàn)證碼”按鈕,如圖10-7所示。圖10-7獲取驗(yàn)證碼當(dāng)輸入用戶名并單擊“獲取驗(yàn)證碼”按鈕時(shí),瀏覽器向Django發(fā)送POST請(qǐng)求,視圖函數(shù)findpsView首先根據(jù)用戶輸入的用戶名在模型User里進(jìn)行數(shù)據(jù)查找,然后判斷用戶名是否存在,若不存在,則會(huì)生成提示信息,如圖10-8所示。圖10-8用戶不存在如果用戶存在,就繼續(xù)判斷會(huì)話Session的VCode是否存在。若不存在,則視圖函數(shù)findpsView通過發(fā)送郵件的方式將驗(yàn)證碼發(fā)送到用戶郵箱,實(shí)現(xiàn)過程如下:●設(shè)置模板上下文button、tips、password和VCodeInfo的值,在網(wǎng)頁(yè)上生成提示信息、密碼輸入框和驗(yàn)證碼輸入框。●驗(yàn)證碼是使用random模塊隨機(jī)生成長(zhǎng)度為4位的整數(shù),然后將驗(yàn)證碼寫入會(huì)話Session的VCode,其作用是與用戶輸入的驗(yàn)證碼進(jìn)行匹配。●郵件發(fā)送是由內(nèi)置函數(shù)email_user實(shí)現(xiàn)的,該方法是模型User特有的方法之一,只適用于模型User?!裼脩羿]箱信息來自于模型User的字段email,如果當(dāng)前用戶的郵箱信息為空,Django就無法發(fā)送郵件。郵件發(fā)送如圖10-9所示。圖10-9郵件發(fā)送用戶接收到驗(yàn)證碼之后,可以在網(wǎng)頁(yè)上輸入用戶名、重置密碼和驗(yàn)證碼,然后單擊“重置密碼”按鈕,這時(shí)將會(huì)觸發(fā)POST請(qǐng)求,函數(shù)findpsView獲取用戶輸入的驗(yàn)證碼并與會(huì)話Session的VCode進(jìn)行對(duì)比,如果兩者不符合,就說明用戶輸入的驗(yàn)證碼與郵件中的驗(yàn)證碼無法匹配,系統(tǒng)提示驗(yàn)證碼錯(cuò)誤,如圖10-10所示。圖10-10驗(yàn)證碼錯(cuò)誤若用戶輸入的驗(yàn)證碼與會(huì)話Session的VCode匹配符合,則程序?qū)?zhí)行密碼修改。首先獲取用戶輸入的密碼,然后使用函數(shù)make_password對(duì)密碼進(jìn)行加密處理并保存在模型User中,最后刪除會(huì)話Session的VCode,否則會(huì)話Session的VCode一直存在,在下次獲取驗(yàn)證碼時(shí),程序就不會(huì)執(zhí)行郵件發(fā)送功能。運(yùn)行結(jié)果如圖10-11所示。圖10-11運(yùn)行結(jié)果上述例子是使用內(nèi)置函數(shù)email_user發(fā)送郵件驗(yàn)證碼,除此之外,Django還提供了多種郵件發(fā)送方法。我們?cè)贒jango的Shell模式下進(jìn)行講解,代碼如下:D:\MyDjango>pythonmanage.pyshell
#使用send_mail實(shí)現(xiàn)郵件發(fā)送
>>>fromdjango.core.mailimportsend_mail
>>>fromdjango.confimportsettings
#獲取settings.py的配置信息
>>>from_email=settings.DEFAULT_FROM_EMAIL
>>>sending=['554301449@']
#發(fā)送郵件,接收郵件以列表表示,說明可設(shè)置多個(gè)接收對(duì)象
>>>send_mail('Django','Django',from_email,sending)
#使用send_mass_mail實(shí)現(xiàn)多封郵件同時(shí)發(fā)送
>>>fromdjango.core.mailimportsend_mass_mail
>>>message1=('Django','Django',from_email,sending)
>>>message2=('Django','Django',from_email,sending)
>>>send_mass_mail((message1,message2),fail_silently=False)
#使用EmailMultiAlternatives實(shí)現(xiàn)郵件發(fā)送
>>>fromdjango.core.mailimportEmailMultiAlternatives
>>>content='<p>這是一封<h3>重要的</h3>郵件。</p>'
>>>msg=EmailMultiAlternatives('MyDjango',content,from_email,sending)
#將正文設(shè)置為HTML格式
>>>msg.content_subtype='html'
#attach_alternative對(duì)正文內(nèi)容進(jìn)行補(bǔ)充和添加
>>>msg.attach_alternative('<h3>Django</h3>','text/html')
#添加附件(可選)
>>>msg.attach_file('D://attachfile.csv')
#發(fā)送
>>>msg.send()
上述代碼分別講述了send_mail、send_mass_mail和EmailMultiAlternatives的使用方法,三者之間的對(duì)比說明如下:●使用send_mail每次發(fā)送郵件都會(huì)建立一個(gè)新的連接,如果發(fā)送多封郵件,就需要建立多個(gè)連接?!駍end_mass_mail是建立單個(gè)連接發(fā)送多封郵件,所以一次性發(fā)送多封郵件時(shí),send_mass_mail要優(yōu)于send_mail?!馝mailMultiAlternatives比前兩者更為個(gè)性化,可以將郵件正文內(nèi)容設(shè)為HTML格式的,也可以在郵件上添加附件,滿足多方面的開發(fā)需求。10.3模型User的擴(kuò)展與使用在開發(fā)過程中,模型User的字段可能滿足不了復(fù)雜的開發(fā)需求?,F(xiàn)在大多數(shù)網(wǎng)站的用戶信息都有用戶的手機(jī)號(hào)碼、QQ號(hào)碼和微信賬號(hào)等一系列個(gè)人信息。為了滿足各種需求,Django提供了以下4種模型擴(kuò)展的方法。代理模型:這是一種模型繼承,這種模型在數(shù)據(jù)庫(kù)中無須創(chuàng)建新數(shù)據(jù)表。一般用于改變現(xiàn)有模型的行為方式,如增加新方法函數(shù)等,并且不影響數(shù)據(jù)表的結(jié)構(gòu)。如果不需要在數(shù)據(jù)表存儲(chǔ)額外的信息,只是增加模型User的操作方法或更改模型的查詢方式,那么可以使用代理模型擴(kuò)展模型User。Profile擴(kuò)展模型User:當(dāng)存儲(chǔ)的信息與模型User相關(guān),而且不改變模型User的內(nèi)置方法時(shí),可定義新的模型MyUser,并設(shè)置某個(gè)字段為OneToOneField,這樣能與模型User形成一對(duì)一關(guān)系,該方法稱為用戶配置(UserProfile)。AbstractBaseUser擴(kuò)展模型User:當(dāng)模型User的內(nèi)置方法不符合開發(fā)需求時(shí),可使用該方法對(duì)模型User重新自定義設(shè)計(jì),該方法對(duì)模型User和數(shù)據(jù)表結(jié)構(gòu)造成較大影響。AbstractUser擴(kuò)展模型User:如果模型User的內(nèi)置方法符合開發(fā)需求,在不改變這些函數(shù)方法的情況下,添加模型User的額外字段,可通過AbstractUser方式替換原有的模型User。上述4種方法各有優(yōu)缺點(diǎn),一般情況下,建議使用AbstractUser擴(kuò)展模型User,因?yàn)樵摲绞綄?duì)原有模型User影響較小而且無須額外創(chuàng)建數(shù)據(jù)表。在講述如何擴(kuò)展模型User之前,首先深入了解模型User的定義過程。在PyCharm里打開模型User的源碼文件,如圖10-12所示。圖10-12模型User的源碼文件模型User繼承父類AbstractUser,而AbstractUser繼承父類AbstractBaseUser和PermissionsMixin,因此模型User的繼承關(guān)系如圖10-13所示。圖10-13模型User的繼承關(guān)系從圖10-13得知,模型User的字段和方法是由父類AbstractUser、AbstractBaseUser和PermissionsMixin定義的,模型字段已在10.1節(jié)的表10-1列舉說明,本節(jié)只列舉說明模型User的內(nèi)置方法,分別說明如下:●get_full_name():由AbstractUser定義,獲取用戶的全名,即字段first_name與last_name的組合值?!駁et_short_name():由AbstractUser定義,獲取模型字段first_name的值?!馿mail_user():由AbstractUser定義,發(fā)送郵件。參數(shù)subject設(shè)置郵件標(biāo)題;參數(shù)message設(shè)置郵件內(nèi)容;參數(shù)from_email設(shè)置發(fā)送郵件的賬號(hào),即配置文件settings.py的DEFAULT_FROM_EMAIL?!駍ave():由AbstractBaseUser定義,定義模型的數(shù)據(jù)保存方式。●get_username():由AbstractBaseUser定義,獲取當(dāng)前用戶的賬號(hào)信息,即模型字段username?!駍et_password():由AbstractBaseUser定義,更改當(dāng)前用戶的密碼,即更改模型字段password。●check_password():由AbstractBaseUser定義,驗(yàn)證加密前的密碼與加密后的密碼是否相同?!駁et_session_auth_hash():由AbstractBaseUser定義,獲取模型字段password的HMAC,在更改密碼時(shí)可使當(dāng)前用戶的登錄狀態(tài)失效。●set_unusable_password():由AbstractBaseUser定義,標(biāo)記用戶尚未設(shè)置密碼?!駂as_usable_password():由AbstractBaseUser定義,檢測(cè)用戶是否尚未設(shè)置密碼?!駁et_group_permissions():由PermissionsMixin定義,獲取當(dāng)前用戶所在用戶組的權(quán)限?!駁et_all_permissions():由PermissionsMixin定義,獲取當(dāng)前用戶所擁有的權(quán)限。●has_perm():由PermissionsMixin定義,判斷當(dāng)前用戶是否具有某個(gè)權(quán)限,參數(shù)perm代表權(quán)限的名稱,以字符串表示。●has_perms():由PermissionsMixin定義,判斷當(dāng)前用戶是否具有多個(gè)權(quán)限,參數(shù)perm_list代表多個(gè)權(quán)限的集合,以列表表示?!駂as_module_perms():由PermissionsMixin定義,判斷當(dāng)前用戶是否具有某個(gè)項(xiàng)目應(yīng)用的所有權(quán)限,參數(shù)app_label代表項(xiàng)目應(yīng)用的名稱。下一步講述如何使用AbstractUser擴(kuò)展模型User。以MyDjango為例,打開項(xiàng)目的數(shù)據(jù)庫(kù)db.sqlite3文件,清除數(shù)據(jù)庫(kù)所有的數(shù)據(jù)表,在user的models.py中定義模型MyUser,代碼如下:#user的models.py
fromdjango.dbimportmodels
fromdjango.contrib.auth.modelsimportAbstractUser
classMyUser(AbstractUser):
qq=models.CharField('QQ號(hào)碼',max_length=16)
weChat=models.CharField('微信賬號(hào)',max_length=100)
mobile=models.CharField('手機(jī)號(hào)碼',max_length=11)
#設(shè)置返回值
def__str__(self):
returnself.username
模型MyUser繼承AbstractUser類,AbstractUser類是模型User的父類,因此模型MyUser也具有模型User的全部字段。在執(zhí)行數(shù)據(jù)遷移之前,必須在項(xiàng)目的settings.py中配置相關(guān)信息,配置信息如下:#settings.py
AUTH_USER_MODEL='user.MyUser'
配置信息是將內(nèi)置模型User替換成自定義的模型MyUser,若沒有設(shè)置配置信息,則在創(chuàng)建數(shù)據(jù)表的時(shí)候,Django分別創(chuàng)建數(shù)據(jù)表auth_user和user_myuser,這樣模型MyUser無法取代內(nèi)置模型User。在PyCharm的Terminal下執(zhí)行數(shù)據(jù)遷移,代碼如下:D:\MyDjango>pythonmanage.pymakemigrations
Migrationsfor'user':
user\migrations\0001_initial.py
-CreatemodelMyUser
D:\MyDjango>pythonmanage.pymigrate
完成數(shù)據(jù)遷移后,打開數(shù)據(jù)庫(kù)查看數(shù)據(jù)表信息,可以發(fā)現(xiàn)內(nèi)置模型User的數(shù)據(jù)表auth_user改為數(shù)據(jù)表user_myuser,并且數(shù)據(jù)表user_myuser的字段除了具有內(nèi)置模型User的字段之外,還額外增加了自定義的字段,如圖10-14所示。圖10-14數(shù)據(jù)表user_myuser使用AbstractUser擴(kuò)展模型User的實(shí)質(zhì)是重新自定義模型User,將內(nèi)置模型User替換成自定義的模型MyUser,替換過程可分為兩個(gè)步驟?!穸x新的模型MyUser,該模型必須繼承AbstractUser類,在模型MyUser里定義的字段為擴(kuò)展字段?!裨陧?xiàng)目的配置文件settings.py中配置AUTH_USER_MODEL信息,在數(shù)據(jù)遷移時(shí),將內(nèi)置模型User替換成自定義的模型MyUser。完成模型MyUser的自定義及數(shù)據(jù)遷移后,接著探討模型MyUser與內(nèi)置模型User在開發(fā)過程中是否存在使用上的差異。首先使用Django內(nèi)置命令pythonmanage.pycreatesuperuser創(chuàng)建超級(jí)管理員并登錄Admin后臺(tái)系統(tǒng),如圖10-15所示。圖10-15Admin后臺(tái)系統(tǒng)從圖10-15中發(fā)現(xiàn),認(rèn)證與授權(quán)沒有顯示用戶信息表,因?yàn)槟P蚆yUser是在user的models.py中定義的。若將模型MyUser展示在后臺(tái)系統(tǒng),則可以在user的admin.py和初始化文件__init__.py中定義相關(guān)的數(shù)據(jù)對(duì)象,代碼如下:重啟MyDjango項(xiàng)目并再次進(jìn)入Admin后臺(tái)系統(tǒng),可以在頁(yè)面上看到模型MyUser所生成的“用戶”,如圖10-16所示。圖10-16模型MyUser的用戶鏈接從用戶數(shù)據(jù)列表頁(yè)進(jìn)入用戶數(shù)據(jù)修改頁(yè)或用戶數(shù)據(jù)新增頁(yè)的時(shí)候,發(fā)現(xiàn)用戶數(shù)據(jù)修改頁(yè)或用戶數(shù)據(jù)新增頁(yè)出現(xiàn)了用戶的手機(jī)號(hào)碼、QQ號(hào)碼和微信賬號(hào)的文本輸入框,這是由MyUserAdmin重寫屬性fieldsets實(shí)現(xiàn)的,如圖10-17所示。圖10-17修改用戶數(shù)據(jù)admin.py定義的MyUserAdmin繼承自UserAdmin,UserAdmin是內(nèi)置模型User的Admin數(shù)據(jù)對(duì)象,換句話說,MyUserAdmin通過繼承UserAdmin并重寫父類的某些屬性和方法能使自定義模型MyUser展示在Admin后臺(tái)系統(tǒng)。UserAdmin的定義過程可以在Django源碼文件django\contrib\auth\admin.py中查看。除了UserAdmin之外,還可以繼承內(nèi)置模型User定義的表單類。內(nèi)置表單類可以在源碼文件django\contrib\auth\forms.py中查看,從源碼中發(fā)現(xiàn),forms.py定義了多個(gè)內(nèi)置表單類,其說明如下:●UserCreationForm:表單字段為username、password1和password2,創(chuàng)建新的用戶信息?!馯serChangeForm:表單字段為password和模型User所有字段,修改已有的用戶信息?!馎uthenticationForm:表單字段為username和password,用戶登錄時(shí)所觸發(fā)的認(rèn)證功能。●PasswordResetForm:表單字段為email,將重置密碼通過發(fā)送郵件的方式實(shí)現(xiàn)密碼找回。●SetPasswordForm:表單字段為password1和password2,修改或新增用戶密碼?!馪asswordChangeForm:表單字段為old_password、new_password1和new_password2,繼承SetPasswordForm,如果是修改密碼,就需要對(duì)舊密碼進(jìn)行驗(yàn)證。●AdminPasswordChangeForm:表單字段為password1和password2,用于Admin后臺(tái)修改用戶密碼。從上述的內(nèi)置表單類發(fā)現(xiàn),這些表單都是在內(nèi)置模型User的基礎(chǔ)上實(shí)現(xiàn)的,但這些表單類不一定適用于自定義模型MyUser。但我們可以自定義模型MyUser的表單類,并繼承上述的內(nèi)置表單類,從而使定義的表單類適用于模型MyUser。以內(nèi)置表單類UserCreationForm為例,使用表單類UserCreationForm實(shí)現(xiàn)用戶注冊(cè)功能。在user中創(chuàng)建form.py文件,并在文件下編寫以下代碼:自定義表單類MyUserCreationForm繼承表單類UserCreationForm,并且重寫Meta的屬性model和fields,分別設(shè)置表單類綁定的模型和字段。最后在MyDjango的urls.py、user的urls.py、views.py和模板文件user.html中實(shí)現(xiàn)用戶注冊(cè)功能,代碼如下:視圖函數(shù)registerView使用自定義表單類MyUserCreationForm實(shí)現(xiàn)用戶注冊(cè)功能,實(shí)現(xiàn)過程如下:(1)在瀏覽器上訪問:8000時(shí),視圖函數(shù)將表單類MyUserCreationForm實(shí)例化并傳遞給模板文件user.html,在瀏覽器上生成用戶注冊(cè)頁(yè)面。(2)輸入用戶信息并單擊“注冊(cè)”按鈕,視圖函數(shù)registerView收到POST請(qǐng)求,將表單數(shù)據(jù)交給表單類MyUserCreationForm處理并生成user對(duì)象。(3)驗(yàn)證user對(duì)象的數(shù)據(jù)信息,如果驗(yàn)證成功,就將數(shù)據(jù)保存到數(shù)據(jù)表user_myuser中,并在網(wǎng)頁(yè)上提示“注冊(cè)成功”;若驗(yàn)證失敗,則在網(wǎng)頁(yè)上提示“注冊(cè)失敗”并清空表單數(shù)據(jù)。(4)注冊(cè)用戶的時(shí)候,表單類MyUserCreationForm對(duì)密碼的安全強(qiáng)度有嚴(yán)格的要求,如9.4節(jié)的圖9-19所示,建議讀者設(shè)置安全強(qiáng)度較高的密碼,密碼過于簡(jiǎn)單會(huì)無法完成注冊(cè)。10.4權(quán)限的設(shè)置與使用用戶權(quán)限是對(duì)不同用戶設(shè)置不同的功能使用權(quán)限,而每個(gè)功能主要以模型來劃分。以10.3節(jié)的MyDjango項(xiàng)目為例,在Admin后臺(tái)系統(tǒng)的用戶數(shù)據(jù)修改頁(yè)或用戶數(shù)據(jù)新增頁(yè)可以查看并設(shè)置用戶權(quán)限,如圖10-18所示。圖10-18用戶權(quán)限在圖10-18的左側(cè)列表框中列出了整個(gè)項(xiàng)目的用戶權(quán)限,每個(gè)權(quán)限以“項(xiàng)目應(yīng)用|模型|模型使用權(quán)限”的格式表示,以u(píng)ser|用戶|Canadduser為例,說明如下:●user是項(xiàng)目應(yīng)用user的名稱?!裼脩羰琼?xiàng)目應(yīng)用user定義的模型MyUser?!馛anadduser是模型MyUser新增數(shù)據(jù)的權(quán)限。當(dāng)執(zhí)行數(shù)據(jù)遷移時(shí),每個(gè)模型默認(rèn)擁有增(Add)、改(Change)、刪(Delete)和查(View)權(quán)限。數(shù)據(jù)遷移成功后,可以在數(shù)據(jù)庫(kù)中查看數(shù)據(jù)表auth_permission的數(shù)據(jù)信息,每行數(shù)據(jù)代表項(xiàng)目中某個(gè)模型的某個(gè)權(quán)限,如圖10-19所示。圖10-19數(shù)據(jù)表auth_permission設(shè)置用戶權(quán)限實(shí)質(zhì)上是對(duì)數(shù)據(jù)表user_myuser和auth_permission之間的數(shù)據(jù)設(shè)置多對(duì)多關(guān)系。首先需要了解用戶、用戶權(quán)限和用戶組三者之間的關(guān)系,以MyDjango的數(shù)據(jù)表為例,如圖10-20所示。圖10-20MyDjango的數(shù)據(jù)表信息從整個(gè)項(xiàng)目的數(shù)據(jù)表看到,用戶、用戶權(quán)限和用戶組分別對(duì)應(yīng)數(shù)據(jù)表user_myuser、auth_permission和auth_group。無論是設(shè)置用戶權(quán)限、設(shè)置用戶所屬用戶組或者設(shè)置用戶組的權(quán)限,它們的本質(zhì)都是對(duì)兩個(gè)數(shù)據(jù)表之間的數(shù)據(jù)建立多對(duì)多的數(shù)據(jù)關(guān)系,說明如下:●數(shù)據(jù)表user_myuser_user_permissions:管理數(shù)據(jù)表user_myuser和auth_permission之間的多對(duì)多關(guān)系,設(shè)置用戶所擁有的權(quán)限。●數(shù)據(jù)表user_myuser_groups:管理數(shù)據(jù)表user_myuser和auth_group之間的多對(duì)多關(guān)系,設(shè)置用戶所在的用戶組?!駭?shù)據(jù)表auth_group_permissions:管理數(shù)據(jù)表auth_group和auth_permission之間的多對(duì)多關(guān)系,設(shè)置用戶組所擁有的權(quán)限。在設(shè)置用戶權(quán)限時(shí),如果用戶的角色是超級(jí)管理員,該用戶就無須設(shè)置權(quán)限,因?yàn)槌?jí)管理員已默認(rèn)具備整個(gè)系統(tǒng)的所有權(quán)限,而設(shè)置用戶權(quán)限只適用于非超級(jí)管理員的用戶。我們?cè)贏dmin后臺(tái)系統(tǒng)創(chuàng)建普通用戶root,然后在PyCharm的Terminal下開啟Django的Shell模式實(shí)現(xiàn)用戶權(quán)限設(shè)置,代碼如下:D:\MyDjango>pythonmanage.pyshell
#導(dǎo)入模型MyUser
>>>fromuser.modelsimportMyUser
#查詢用戶信息
>>>user=MyUser.objects.filter(username='root')[0]
#判斷當(dāng)前用戶是否具有用戶新增的權(quán)限
#user.add_myuser為固定寫法
#user為項(xiàng)目應(yīng)用的名稱
#add_myuser來自數(shù)據(jù)表auth_permission的字段codename
>>>user.has_perm('user.add_myuser')
False
#導(dǎo)入模型Permission
>>>fromdjango.contrib.auth.modelsimportPermission
#在權(quán)限管理表獲取權(quán)限add_myuser的數(shù)據(jù)對(duì)象permission
>>>p=Permission.objects.filter(codename='add_myuser')[0]
#對(duì)當(dāng)前用戶對(duì)象user設(shè)置權(quán)限add_myuser
#user_permissions是多對(duì)多的模型字段
#該字段由內(nèi)置模型User的父類PermissionsMixin定義
>>>user.user_permissions.add(p)
#再次判斷當(dāng)前用戶是否具有用戶新增的權(quán)限
>>>user=MyUser.objects.filter(username='root')[0]
>>>user.has_perm('user.add_myuser')
True
上述代碼首先查詢用戶名為root的用戶是否具備用戶新增的權(quán)限,然后對(duì)該用戶設(shè)置用戶新增的權(quán)限,設(shè)置方式是由多對(duì)多的模型字段user_permissions調(diào)用add方法實(shí)現(xiàn)的。打開數(shù)據(jù)表user_myuser_user_permissions可以看到新增了一行數(shù)據(jù),如圖10-21所示。圖10-21數(shù)據(jù)表user_myuser_user_permissions從圖10-21看到,表字段myuser_id和permission_id分別是數(shù)據(jù)表user_myuser和auth_permission的主鍵,每一行數(shù)據(jù)代表某個(gè)用戶具有某個(gè)模型的某個(gè)操作權(quán)限。除了添加權(quán)限之外,還可以對(duì)用戶的權(quán)限進(jìn)行刪除和查詢,代碼如下:#導(dǎo)入模型MyUser
>>>fromuser.modelsimportMyUser
#導(dǎo)入模型Permission
>>>fromdjango.contrib.auth.modelsimportPermission
#查詢用戶信息
>>>user=MyUser.objects.filter(username='root')[0]
#查詢用戶新增的權(quán)限
>>>p=Permission.objects.filter(codename='add_myuser')[0]
#刪除某條權(quán)限
>>>user.user_permissions.remove(p)
#判斷是否已刪除權(quán)限,若為False,則說明刪除成功
#函數(shù)has_perm用于判斷用戶是否擁有權(quán)限
>>>user.has_perm('user.add_myuser')
False
#清空當(dāng)前用戶全部權(quán)限
>>>user.user_permissions.clear()
#獲取當(dāng)前用戶所擁有的權(quán)限信息
#將上述刪除的權(quán)限添加到數(shù)據(jù)表再查詢
>>>user.user_permissions.add(p)
#查詢數(shù)據(jù)表user_myuser_user_permissions的數(shù)據(jù)
#查詢方式是使用ORM框架的API方法
>>>user.user_permissions.values()
10.5自定義用戶權(quán)限一般情況下,每個(gè)模型默認(rèn)擁有增(Add)、改(Change)、刪(Delete)和查(View)權(quán)限。但實(shí)際開發(fā)中可能要對(duì)某個(gè)模型設(shè)置特殊權(quán)限,比如QQ音樂只允許會(huì)員播放高質(zhì)音樂。為了解決這種開發(fā)需求,在定義模型時(shí),可以在模型的屬性Meta中設(shè)置自定義權(quán)限。以10.3節(jié)的MyDjango項(xiàng)目為例,對(duì)user的模型MyUser重新定義,代碼如下:模型MyUser的Meta繼承父類AbstractUser的Meta,并且新增permissions屬性,這樣就能創(chuàng)建用戶權(quán)限,模型MyUser的Meta必須繼承父類AbstractUser的Meta,因?yàn)锳bstractUser的Meta定義屬性verbose_name、verbose_name_plural和abstract。新增屬性permissions以元組或列表的數(shù)據(jù)格式表示,元組或列表的每個(gè)元素代表一個(gè)權(quán)限,每個(gè)權(quán)限以元組或列表表示。一個(gè)權(quán)限中含有兩個(gè)元素,如上述的('vip_myuser','Canvipuser'),vip_myuser和Canvipuser分別是數(shù)據(jù)表auth_permission的codename和name字段。下一步在數(shù)據(jù)庫(kù)中清除MyDjango原有的數(shù)據(jù)表,并在PyCharm的Terminal中重新執(zhí)行數(shù)據(jù)遷移,代碼如下:D:\MyDjango>pythonmanage.pymakemigrations
Migrationsfor'user':
user\migrations\0001_initial.py
-CreatemodelMyUser
D:\MyDjango>pythonmanage.pymigrate
數(shù)據(jù)遷移執(zhí)行完成后,在數(shù)據(jù)庫(kù)中打開數(shù)據(jù)表auth_permission,可以找到自定義權(quán)限vip_myuser,如圖10-22所示。圖10-22數(shù)據(jù)表auth_permission10.6設(shè)置網(wǎng)頁(yè)的訪問權(quán)限通過前面的學(xué)習(xí),相信大家對(duì)Django的內(nèi)置權(quán)限功能有了一定的了解。本節(jié)將結(jié)合示例講述如何在網(wǎng)頁(yè)中設(shè)置用戶的訪問權(quán)限,以10.5節(jié)的MyDjango項(xiàng)目為例,確保項(xiàng)目應(yīng)用user已定義模型MyUser,并且數(shù)據(jù)表auth_permission已記錄權(quán)限vip_myuser的數(shù)據(jù)信息。我們?cè)贛yDjango的項(xiàng)目應(yīng)用user里實(shí)現(xiàn)用戶注冊(cè)、登錄和注銷功能,并且增加用戶中心,用于檢驗(yàn)用戶是否具有vip_myuser權(quán)限。在編寫代碼之前,需要對(duì)MyDjango的目錄結(jié)構(gòu)進(jìn)行調(diào)整,在templates文件夾放置模板文件info.html,在static文件夾放置模板文件的靜態(tài)資源,并且user的form.py文件已定義MyUserCreationForm表單類(定義過程可回顧10.3節(jié)),用于實(shí)現(xiàn)用戶注冊(cè)和登錄功能。下一步實(shí)現(xiàn)用戶注冊(cè)、登錄、注銷和用戶中心頁(yè),分別在MyDjango的urls.py和user的urls.py中定義路由信息,代碼如下:#MyDjango的urls.py
fromdjango.urlsimportpath,include
fromdjango.contribimportadmin
urlpatterns=[
path('admin/',admin.site.urls),
path('',include(('user.urls','user'),namespace='user')),
]
#user的urls.py
fromdjango.urlsimportpath
from.viewsimport*
urlpatterns=[
#用戶注冊(cè)
path('',registerView,name='register'),
#用戶登錄
path('login.html',loginView,name='login'),
#用戶注銷
path('logout.html',logoutView,name='logout'),
#用戶中心
path('info.html',infoView,name='info')
]
項(xiàng)目應(yīng)用user的urls.py中定義了4條路由信息,它們實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的操作流程,流程順序?yàn)橛脩糇?cè)→用戶登錄→用戶中心→用戶注銷。然后在user的views.py中定義相關(guān)的視圖函數(shù),代碼如下:上述代碼分別定義視圖函數(shù)registerView、loginView、logoutView和infoView,函數(shù)之間通過網(wǎng)頁(yè)跳轉(zhuǎn)方式構(gòu)建關(guān)聯(lián),從而實(shí)現(xiàn)一個(gè)簡(jiǎn)單的操作流程,流程說明如下:(1)當(dāng)用戶訪問:8000時(shí),瀏覽器將呈現(xiàn)用戶注冊(cè)頁(yè)面,輸入新的用戶信息并單擊“確定”按鈕,視圖函數(shù)registerView將收到POST請(qǐng)求,將表單數(shù)據(jù)交由表單類MyUserCreationForm實(shí)現(xiàn)用戶注冊(cè)。(2)如果用戶注冊(cè)失敗,就提示錯(cuò)誤信息并返回用戶注冊(cè)頁(yè)面;如果注冊(cè)成功,就由表單類MyUserCreationForm創(chuàng)建用戶,保存在模型MyUser的數(shù)據(jù)表中。默認(rèn)情況下,新用戶不具備任何權(quán)限,因此視圖函數(shù)registerView為新用戶賦予自定義權(quán)限vip_myuser并跳轉(zhuǎn)到用戶登錄頁(yè)面。(3)在用戶登錄頁(yè)面輸入新用戶的賬號(hào)和密碼并單擊“確定”按鈕,視圖函數(shù)loginView將收到POST請(qǐng)求,從請(qǐng)求參數(shù)獲取用戶信息并進(jìn)行驗(yàn)證。如果用戶驗(yàn)證失敗,就提示錯(cuò)誤信息并返回用戶登錄頁(yè)面;如果用戶驗(yàn)證成功,就執(zhí)行用戶登錄并跳轉(zhuǎn)到用戶中心頁(yè)面。(4)用戶中心頁(yè)面設(shè)有裝飾器permission_required,用于檢測(cè)用戶是否具有vip_myuser權(quán)限。如果用戶權(quán)限檢測(cè)失敗,就跳轉(zhuǎn)到用戶登錄頁(yè)面;如果檢測(cè)成功,就說明當(dāng)前用戶具有vip_myuser權(quán)限,能正常訪問用戶中心頁(yè)面。視圖函數(shù)infoView使用了裝飾器login_required和permission_required,分別對(duì)當(dāng)前用戶的登錄狀態(tài)和用戶權(quán)限進(jìn)行校驗(yàn),兩者的說明如下:(1)login_required用于設(shè)置用戶登錄訪問權(quán)限。如果當(dāng)前用戶在尚未登錄的狀態(tài)下訪問用戶中心頁(yè)面,程序就會(huì)自動(dòng)跳轉(zhuǎn)到指定的路由地址,只有用戶完成登錄后才能正常訪問用戶中心頁(yè)。login_required的參數(shù)有function、redirect_field_name和login_url,參數(shù)說明如下:●參數(shù)function:默認(rèn)值為None,這是定義裝飾器的執(zhí)行函數(shù)?!駞?shù)redirect_field_name:默認(rèn)值是next。當(dāng)?shù)卿洺晒χ?,程序?huì)自動(dòng)跳回之前瀏覽的網(wǎng)頁(yè)?!駞?shù)login_url:設(shè)置用戶登錄的路由地址。默認(rèn)值是settings.py的配置屬性LOGIN_URL,而配置屬性LOGIN_URL需要開發(fā)者自行在settings.py中配置。(2)permission_required用于驗(yàn)證當(dāng)前用戶是否擁有相應(yīng)的權(quán)限。若用戶不具備權(quán)限,則程序?qū)⑻D(zhuǎn)到指定的路由地址或者拋出異常。permission_required的參數(shù)有perm、login_url和raise_exception,參數(shù)說明如下:●參數(shù)perm:必選參數(shù),判斷當(dāng)前用戶是否具備某個(gè)權(quán)限。參數(shù)值為固定格式,如user.vip_myuser,user為項(xiàng)目應(yīng)用名稱,vip_myuser是數(shù)據(jù)表auth_permission的字段codename。●參數(shù)login_url:設(shè)置驗(yàn)證失敗所跳轉(zhuǎn)的路由地址,默認(rèn)值為None。若不設(shè)置參數(shù),則驗(yàn)證失敗后會(huì)拋出404異常?!駞?shù)raise_exception:設(shè)置拋出異常,默認(rèn)值為False。裝飾器permission_required的作用與內(nèi)置函數(shù)has_perm相同,視圖函數(shù)infoView也可以使用函數(shù)has_perm實(shí)現(xiàn)裝飾器permission_required的功能,代碼如下:最后在模板文件user.html和info.html中編寫網(wǎng)頁(yè)代碼,模板文件user.html主要生成用戶注冊(cè)和登錄頁(yè)面;模板文件info.html生成用戶中心頁(yè)面,兩者的代碼如下:模板文件user.html設(shè)置模板上下userLogin、tips和user,每個(gè)上下文的作用說明如下:●userLogin判斷當(dāng)前頁(yè)面的功能類型,從而顯示相應(yīng)的網(wǎng)頁(yè)內(nèi)容,若userLogin的值為False,則當(dāng)前頁(yè)面為用戶注冊(cè)頁(yè)面,否則為用戶登錄頁(yè)面?!駎ips是顯示的提示信息,比如用戶注冊(cè)失敗或用戶不存在等異常信息?!駏ser是表單類MyUserCreationForm的實(shí)例化對(duì)象,由user生成網(wǎng)頁(yè)表單,從而實(shí)現(xiàn)用戶注冊(cè)和登錄功能。模板文件info.html使用模板上下文user和perms,但視圖函數(shù)infoView沒有定義變量user和perms。模板上下文user和perms是在Django解析模板文件的過程中生成的,它們與配置文件settings.py的TEMPLATES設(shè)置有關(guān)。我們查看settings.py的TEMPLATES配置信息,代碼如下:因?yàn)門EMPLATES定義了處理器集合context_processors,所以在解析模板文件之前,Django依次運(yùn)行處理器集合的程序。當(dāng)運(yùn)行到處理器auth時(shí),程序會(huì)生成變量user和perms,并且將變量傳入模板上下文TemplateContext中,因此模板中可以直接使用模板上下文user和perms。運(yùn)行MyDjango項(xiàng)目,在瀏覽器上訪問:8000進(jìn)入用戶注冊(cè)頁(yè)面,創(chuàng)建新用戶root,密碼為mydjango123,然后在用戶登錄頁(yè)面使用新用戶root完成登錄過程,最后在用戶中心頁(yè)面查看相關(guān)的用戶信息,如圖10-23所示。圖10-23用戶中心頁(yè)面如果在Admin后臺(tái)系統(tǒng)創(chuàng)建普通用戶user1,并且該用戶不賦予任何權(quán)限,在用戶登錄頁(yè)面使用user1完成登錄過程,Django就會(huì)重新跳轉(zhuǎn)到用戶登錄頁(yè)面,并且在登錄頁(yè)面的路由地址設(shè)置請(qǐng)求參數(shù)next,這說明當(dāng)前用戶不具備自定義權(quán)限vip_myuser,導(dǎo)致無法訪問用戶中心頁(yè)面,如圖10-24所示。圖10-24用戶登錄頁(yè)面10.7用戶組的設(shè)置與使用用戶組是對(duì)用戶進(jìn)行分組管理,其作用是在權(quán)限控制中可以批量地對(duì)用戶權(quán)限進(jìn)行分配,無需將權(quán)限一個(gè)一個(gè)地分配到每個(gè)用戶,節(jié)省維護(hù)的工作量。將用戶加入某個(gè)用戶組,該用戶就擁有該用戶組所具備的權(quán)限。例如用戶組teachers擁有權(quán)限can_add_lesson,那么所有屬于teachers用戶組的用戶都具備can_add_lesson權(quán)限。我們知道用戶、權(quán)限和用戶組三者之間是多對(duì)多的數(shù)據(jù)關(guān)系,而用戶組可以理解為用戶和權(quán)限之間的中轉(zhuǎn)站。設(shè)置用戶組分為兩個(gè)步驟:設(shè)置用戶組的權(quán)限和設(shè)置用戶組的用戶。設(shè)置用戶組的權(quán)限主要對(duì)數(shù)據(jù)表auth_group和auth_permission構(gòu)建多對(duì)多的數(shù)據(jù)關(guān)系,數(shù)據(jù)關(guān)系保存在數(shù)據(jù)表auth_group_permissions中。以10.6節(jié)的MyDjango項(xiàng)目為例,其數(shù)據(jù)庫(kù)結(jié)構(gòu)如圖10-25所示。圖10-25MyDjango的數(shù)據(jù)表在數(shù)據(jù)表auth_group中新建一行數(shù)據(jù),表字段name為“用戶管理”,當(dāng)前數(shù)據(jù)在項(xiàng)目中代表一個(gè)用戶組;此外,還可以在Admin后臺(tái)系統(tǒng)創(chuàng)建用戶組,但新建的用戶組無須添加任何權(quán)限,如圖10-26所示。圖10-26在Admin后臺(tái)系統(tǒng)創(chuàng)建用戶組下一步對(duì)用戶組“用戶管理”進(jìn)行權(quán)限分配,在PyCharm的Terminal中使用Django的Shell模式實(shí)現(xiàn)用戶組的權(quán)限配置,代碼如下:#用戶組的權(quán)限配置
#導(dǎo)入內(nèi)置模型Group和Permission
>>>fromdjango.contrib.auth.modelsimportGroup
>>>fromdjango.contrib.auth.modelsimportPermission
#獲取某個(gè)權(quán)限對(duì)象p
>>>p=Permission.objects.get(codename='vip_myuser')
#獲取某個(gè)用戶組對(duì)象group
>>>group=Group.objects.get(id=1)
#將權(quán)限對(duì)象p添加到用戶組group中
>>>group.permissions.add(p)
上述代碼將自定義權(quán)限vip_myuser添加到用戶組“用戶管理”,功能實(shí)現(xiàn)過程如下:(1)從數(shù)據(jù)表auth_permission中查詢自定義權(quán)限vip_myuser的對(duì)象p,對(duì)象p是數(shù)據(jù)表字段codename等于vip_myuser的數(shù)據(jù)信息。(2)從數(shù)據(jù)表auth_group中查詢用戶組“用戶管理”的對(duì)象group,對(duì)象group是數(shù)據(jù)表主鍵等于1的數(shù)據(jù)信息。(3)由對(duì)象group使用permissions.add方法將權(quán)限對(duì)象p和用戶組對(duì)象group綁定,在數(shù)據(jù)表auth_group_permission中構(gòu)建多對(duì)多的數(shù)據(jù)關(guān)系,數(shù)據(jù)表的數(shù)據(jù)信息如圖10-27所示。圖10-27數(shù)據(jù)表auth_group_permissions除了添加用戶組的權(quán)限之外,還可以刪除用戶組已有的權(quán)限,代碼如下:#刪除當(dāng)前用戶組group的vip_myuser權(quán)限
>>>group.permissions.remove(p)
#刪除當(dāng)前用戶組group的全部權(quán)限
>>>group.permissions.clear()
最后實(shí)現(xiàn)用戶組的用戶分配,這個(gè)過程是對(duì)數(shù)據(jù)表auth_group和user_myuser構(gòu)建多對(duì)多的數(shù)據(jù)關(guān)系,數(shù)據(jù)關(guān)系保存在數(shù)據(jù)表user_myuser_groups中。在Django的Shell模式下實(shí)現(xiàn)用戶組的用戶分配,代碼如下:#將用戶分配到用戶組
#導(dǎo)入模型Group和MyUser
>>>fromuser.modelsimportMyUser
>>>fromdjango.contrib.auth.modelsimportGroup
#獲取用戶對(duì)象user,代表用戶名為user1的數(shù)據(jù)信息
>>>user=MyUser.objects.get(username='user1')
#獲取用戶組對(duì)象group,代表用戶組“用戶管理”的數(shù)據(jù)信息
>>>group=Group.objects.get(id=1)
#將用戶添加到用戶組
>>>user.groups.add(group)
上述代碼將用戶user1添加到用戶組“用戶管理”,實(shí)現(xiàn)過程與用戶組的權(quán)限設(shè)置有相似之處,只是兩者使用的模型和方法有所不同。查看數(shù)據(jù)表user_myuser_groups,數(shù)據(jù)信息如圖10-28所示。圖10-28數(shù)據(jù)表user_myuser_groups除了添加用戶組的用戶之外,還可以刪除用戶組已有的用戶,代碼如下:#刪除用戶組某一用戶
>>>user.groups.remove(group)
#清空用戶組全部用戶
>>>user.groups.clear()
第11章常用的Web應(yīng)用程序Django為開發(fā)者提供了常見的Web應(yīng)用程序,如會(huì)話控制、緩存機(jī)制、CSRF防護(hù)、消息框架、分頁(yè)功能、國(guó)際化和本地化、單元測(cè)試和自定義中間件。內(nèi)置的Web應(yīng)用程序大大優(yōu)化了網(wǎng)站性能,并且完善了安全防護(hù)機(jī)制,同時(shí)也提高了開發(fā)者的開發(fā)效率。11.1會(huì)話控制Django內(nèi)置的會(huì)話控制簡(jiǎn)稱為Session,可以為用戶提供基礎(chǔ)的數(shù)據(jù)存儲(chǔ)。數(shù)據(jù)主要存儲(chǔ)在服務(wù)器上,并且網(wǎng)站的任意站點(diǎn)都能使用會(huì)話數(shù)據(jù)。當(dāng)用戶第一次訪問網(wǎng)站時(shí),網(wǎng)站的服務(wù)器將自動(dòng)創(chuàng)建一個(gè)Session對(duì)象,該Session對(duì)象相當(dāng)于該用戶在網(wǎng)站的一個(gè)身份憑證,而且Session能存儲(chǔ)該用戶的數(shù)據(jù)信息。當(dāng)用戶在網(wǎng)站的頁(yè)面之間跳轉(zhuǎn)時(shí),存儲(chǔ)在Session對(duì)象中的數(shù)據(jù)不會(huì)丟失,只有Session過期或被清理時(shí),服務(wù)器才將Session中存儲(chǔ)的數(shù)據(jù)清空并終止該Session。11.1.1會(huì)話的配置與操作在4.2.3小節(jié)已講述過Session和Cookie的關(guān)系,本節(jié)將簡(jiǎn)單回顧兩者的關(guān)系,說明如下:●Session存儲(chǔ)在服務(wù)器端,Cookie存儲(chǔ)在客戶端,所以Session的安全性比Cookie高。●當(dāng)獲取某用戶的Session數(shù)據(jù)時(shí),首先從用戶傳遞的Cookie里獲取sessionid,然后根據(jù)sessionid在網(wǎng)站服務(wù)器找到相應(yīng)的Session?!馭ession存放在服務(wù)器的內(nèi)存中,Session的數(shù)據(jù)不斷增加會(huì)造成服務(wù)器的負(fù)擔(dān),因此存放在Session中的數(shù)據(jù)不能過于龐大。在創(chuàng)建Django項(xiàng)目時(shí),Django已默認(rèn)啟用Session功能,每個(gè)用戶的Session通過Django的中間件MIDDLEWARE接收和調(diào)度處理,可以在配置文件settings.py中找到相關(guān)信息,如圖11-1所示。圖11-1Session功能配置當(dāng)訪問網(wǎng)站時(shí),所有的HTTP請(qǐng)求都經(jīng)過中間件處理,而中間件SessionMiddleware會(huì)判斷當(dāng)前請(qǐng)求的用戶身份是否存在,并根據(jù)判斷結(jié)果執(zhí)行相應(yīng)的程序處理。中間件SessionMiddleware相當(dāng)于HTTP請(qǐng)求接收器,根據(jù)請(qǐng)求信息做出相應(yīng)的調(diào)度,而程序的執(zhí)行則由settings.py的配置屬性INSTALLED_APPS的django.contrib.sessions完成,其配置信息如圖11-2所示。圖11-2Session的處理程序django.contrib.sessions實(shí)現(xiàn)了Session的創(chuàng)建和操作處理,如創(chuàng)建或存儲(chǔ)用戶的Session對(duì)象、管理Session的生命周期等。它默認(rèn)使用數(shù)據(jù)庫(kù)存儲(chǔ)Session信息,執(zhí)行數(shù)據(jù)遷移時(shí),在數(shù)據(jù)庫(kù)中可以看到數(shù)據(jù)表django_session,如圖11-3所示。圖11-3數(shù)據(jù)表django_session以10.6節(jié)的MyDjango項(xiàng)目為例,我們將通過例子來講述Session運(yùn)行機(jī)制。首先清除瀏覽器的歷史記錄,確保以游客身份訪問MyDjango,即用戶在未登錄狀態(tài)下訪問Django。在瀏覽器打開開發(fā)者工具并訪問:8000,從開發(fā)者工具的Network標(biāo)簽的All選項(xiàng)里找到:8000的請(qǐng)求信息,若當(dāng)前Cookie沒有生成sessionid,則說明一般情況下,Django不會(huì)為游客身份創(chuàng)建Session,如圖11-4所示。圖11-4Cookie信息訪問用戶登錄頁(yè)面(:8000/login.html)并完成用戶登錄,打開用戶中心頁(yè)面的請(qǐng)求信息,可以看到Cookie生成帶有sessionid的數(shù)據(jù),并且數(shù)據(jù)表dja
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度機(jī)房智能化改造與信息化升級(jí)合同
- 2025年度全球IT產(chǎn)品銷售與技術(shù)服務(wù)合同
- 2025年度人工智能股票借款合同(技術(shù)領(lǐng)先)
- 2025年度光伏扶貧項(xiàng)目施工與設(shè)備供應(yīng)合同
- 2025年度城市綠化提升改造工程合同
- 2025年度文化產(chǎn)業(yè)園建設(shè)貸款合同范本
- 2025年度大數(shù)據(jù)分析團(tuán)隊(duì)招聘合同范本
- 2025年度智慧城市建設(shè)項(xiàng)目合同規(guī)范
- 2025年度城市綜合體建筑工程分包勞務(wù)承包合同
- 2025年度城市綜合體混凝土地面裝飾施工合同
- 唐山動(dòng)物園景觀規(guī)劃設(shè)計(jì)方案
- 中國(guó)版梅尼埃病診斷指南解讀
- 創(chuàng)業(yè)投資管理知到章節(jié)答案智慧樹2023年武漢科技大學(xué)
- 暨南大學(xué)《經(jīng)濟(jì)學(xué)》考博歷年真題詳解(宏觀經(jīng)濟(jì)學(xué)部分)
- GB/T 8014.1-2005鋁及鋁合金陽(yáng)極氧化氧化膜厚度的測(cè)量方法第1部分:測(cè)量原則
- eNSP簡(jiǎn)介及操作課件
- 公文與公文寫作課件
- 運(yùn)動(dòng)技能學(xué)習(xí)與控制課件第七章運(yùn)動(dòng)技能的協(xié)調(diào)控制
- 節(jié)后復(fù)工吊籃驗(yàn)收表格
- 醫(yī)療器械分類目錄2002版
- 氣管套管滑脫急救知識(shí)分享
評(píng)論
0/150
提交評(píng)論