Flask之旅FlaskWeb開發(fā):基于Python的Web應(yīng)用開發(fā)實(shí)戰(zhàn)學(xué)習(xí)筆記_第1頁
Flask之旅FlaskWeb開發(fā):基于Python的Web應(yīng)用開發(fā)實(shí)戰(zhàn)學(xué)習(xí)筆記_第2頁
Flask之旅FlaskWeb開發(fā):基于Python的Web應(yīng)用開發(fā)實(shí)戰(zhàn)學(xué)習(xí)筆記_第3頁
Flask之旅FlaskWeb開發(fā):基于Python的Web應(yīng)用開發(fā)實(shí)戰(zhàn)學(xué)習(xí)筆記_第4頁
Flask之旅FlaskWeb開發(fā):基于Python的Web應(yīng)用開發(fā)實(shí)戰(zhàn)學(xué)習(xí)筆記_第5頁
免費(fèi)預(yù)覽已結(jié)束,剩余24頁可下載查看

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、Flask之旅FlaskWeb開發(fā):基于Python的Web應(yīng)用開發(fā)實(shí)戰(zhàn)學(xué)習(xí)筆記1虛擬環(huán)境2016-6-8書上介紹了virtualenv,每個(gè)venv都會(huì)拷貝一份packages到項(xiàng)目/venv目錄。plainviewplaincopy1. virtualenvvenv2. venvScriptsactivate.bat3. (venv)$pipfreeze>requirements.txt4. (venv)$pipinstall-rrequirements.txt5. piplist-outdated6. pipinstall-upgarade<Package1><P

2、ackageN>比較了一下conda管理環(huán)境,可能conda更勝一籌:點(diǎn)擊打開鏈接或者用virtualenvwrapper:點(diǎn)擊打開鏈接plainviewplaincopy1. gittag列出所有打tag的分支2. gitcheckout<tag_name>切換至Utag3. gitreset-hard不保留修改.gitignore:指定哪些文件或目錄不作同步,比如./venv/,*.pyc,數(shù)據(jù)庫(kù)文件.sqlite3,.mysql推薦IDE:PyCharm2016.1導(dǎo)入已有的virtualenv:File->Setting->ProjectInterprat

3、er->選擇項(xiàng)目目錄下的/venv/Python特點(diǎn):- >newFlaskProject- >jumpbetweenViewfuncionandTemplates- >Git2基本結(jié)構(gòu)初始化:pythonviewplaincopy1. #-*-coding:utf-8-*-2. fromflaskimportFlask3. app=Flask(_name_)Flask類的構(gòu)造函數(shù)只有一個(gè)必須指定的參數(shù),即程序主模塊或包的名字。在大多數(shù)程序中,Python的_name_變量就是所需的值。Flask用這個(gè)參數(shù)決定程序的根目錄,以便稍后能夠找到相對(duì)于程序根目錄的資源文件位置

4、路由(route)和視圖函數(shù)(viewfunction):定義路由的最簡(jiǎn)便方式,是使用程序?qū)嵗峁┑腶pp.route修飾器,把修飾的函數(shù)注冊(cè)為路由pythonviewplaincopy1. app.route('/')2. defindex():3. return'<h1>HelloWorld!</h1>'修飾器是Python語言的標(biāo)準(zhǔn)特性,可以使用不同的方式修改函數(shù)的行為。慣常用法是使用修飾器把函數(shù)注冊(cè)為事件的處理程序。動(dòng)態(tài)路由:地址中可以包含可變部分,F(xiàn)lask支持在路由中使用int、float和path類型。path類型也是字符串

5、,但不把斜線視作分隔符pythonviewplaincopy1. app.route('/user/<name>')2. defuser(name):3. return'<h1>Hello,%s!</h1>'%name4. app.route('/user/<int:id>')#不能有空格!默認(rèn)端口是5000,可以改成其它的(flask_script.Manager也有此功能)#有些端口不能用,查詢已占用的端口:netstat-ano;netstat-aon|findstr"6000&qu

6、ot;tasklist|findstr"<PID>"taskkill/f/t/imXXX.exepythonviewplaincopy1.app.run(debug=True,port=7777)1. 公認(rèn)端口(WellKnownPorts):從0至U1023,緊密綁定(binding)于一些服務(wù)。通常這些端口的通訊明確表明了某種服務(wù)協(xié)議。80端口實(shí)際上總是HTTP通訊。2. 注冊(cè)端口(RegisteredPorts):從1024到49151。它們松散地綁定于一些服務(wù)。這些端口同樣用于許多其它目的。例如:許多系統(tǒng)處理動(dòng)態(tài)端口從1024左右開始。3. 動(dòng)態(tài)和/或私

7、有端口(Dynamicand/orPrivatePorts):從49152至U65535。理論上,不應(yīng)為服務(wù)分配這些端口。實(shí)際上,機(jī)器通常從1024起分配動(dòng)態(tài)端口。請(qǐng)求-響應(yīng)循環(huán)Context上下文全局變量:?current_app程序上下文當(dāng)前激活程序的程序?qū)嵗?g程序上下文處理請(qǐng)求時(shí)用作臨時(shí)存儲(chǔ)的對(duì)象。每次請(qǐng)求都會(huì)重設(shè)這個(gè)變量?request請(qǐng)求上下文請(qǐng)求對(duì)象,封裝了客戶端發(fā)出的HTTP請(qǐng)求中的內(nèi)容?session請(qǐng)求上下文用戶會(huì)話,用于存儲(chǔ)請(qǐng)求之間需要“記住”的值的詞典URL映射是URL和視圖函數(shù)之間的對(duì)應(yīng)關(guān)系。Flask使用app.route修飾器或者非修飾器形式的app.add_ur

8、l_rule()生成映射。pythonviewplaincopy1. app.url_map2. Map(<Rule'/'(HEAD,OPTIONS,GET)->index>,3. <Rule'/static/<filename>'(HEAD,OPTIONS,GET)->static>,4. <Rule'/user/<name>'(HEAD,OPTIONS,GET)->user>)HEAD、Options>GET是請(qǐng)求方法,由路由進(jìn)行處理。Flask為每個(gè)路由都指

9、定了請(qǐng)求方法,這樣不同的請(qǐng)求方法發(fā)送到相同的URL上時(shí),會(huì)使用不同的視圖函數(shù)進(jìn)行處理。HEAD和OPTIONS方法由Flask自動(dòng)處理請(qǐng)求Hook:在請(qǐng)求鉤子函數(shù)和視圖函數(shù)之間共享數(shù)據(jù)一般使用上下文全局變量g1. before_first_request?:注冊(cè)一個(gè)函數(shù),在處理第一個(gè)請(qǐng)求之前運(yùn)行。2. before_request?:注冊(cè)一個(gè)函數(shù),在每次請(qǐng)求之前運(yùn)行。3. after_request?:注冊(cè)一個(gè)函數(shù),如果沒有未處理的異常拋出,在每次請(qǐng)求之后運(yùn)行。4. teardown_request?:注冊(cè)一個(gè)函數(shù),即使有未處理的異常拋出,也在每次請(qǐng)求之后運(yùn)行響應(yīng)(視圖函數(shù)返回)?make_r

10、esponse()函數(shù)可接受1-3個(gè)參數(shù)(html,狀態(tài)碼,header)pythonviewplaincopy1. response=make_response('<h1>Thisdocumentcarriesacookie!</h1>',200)2. response.set_cookie('answer','42')3. returnresponse?重定向的特殊響應(yīng)類型,302:returnredirect('http:')?特殊的響應(yīng)由abort函數(shù)生成,用于處理錯(cuò)誤:abort(404)Flas

11、k擴(kuò)展原書更正:Importingflask.ext.scriptisdeprecated,useflask_scriptinstead.4. 模板template業(yè)務(wù)邏輯和表現(xiàn)邏輯要分開按功能分(模板不需要重用時(shí)),或按Division分(大部分模板需要重用時(shí))Jinja2模板引擎模板是一個(gè)包含響應(yīng)文本的文彳其中包含用占位變量.表示的動(dòng)態(tài)部分,其具體值只在請(qǐng)求的上下文中才能知道。使用真實(shí)值替換變量,再返回最終得到的響應(yīng)字符串,這一過程稱為渲染。pythonviewplaincopy1. app.route('/user/<name>')2. defuser(nam

12、e):3. returnrender_template('user.html',name=name)模板變量Jinja2能識(shí)別所有類型的變量,甚至是一些復(fù)雜的類型,例如列表、字典和對(duì)象htmlviewplaincopy1. <p>Avaluefromadictionary:mydict'key'.</p>2. <p>Avaluefromalist:mylist3.</p>3. <p>Avaluefromalist,withavariableindex:mylistmyintvar.</p>4

13、. <p>Avaluefromanobject'smethod:myobj.somemethod().</p>可以使用過濾器修改變量。千萬別在不可信的值上使用safe過濾器,例如用戶在表單中輸入的文本htmlviewplaincopy1.Hello,name|capitalize完整的過濾器列表?safe渲染值時(shí)不轉(zhuǎn)義。默認(rèn)情況下,出于安全考慮,Jinja2會(huì)轉(zhuǎn)義所有變量?capitalize把值的首字母轉(zhuǎn)換成大寫,其他字母轉(zhuǎn)換成小寫?lower把值轉(zhuǎn)換成小寫形式?upper把值轉(zhuǎn)換成大寫形式?title把值中每個(gè)單詞的首字母都轉(zhuǎn)換成大寫?trim把值的首尾空格

14、去掉?striptags渲染之前把值中所有的HTML標(biāo)簽都刪掉控制結(jié)構(gòu)%.%,可用來改變模板的渲染流程if,for,macro,import,include需要在多處重復(fù)使用的模板代碼片段可以寫入單獨(dú)的文件,再包含%include'common.html'%在所有模板中另一種重復(fù)使用代碼的強(qiáng)大方式是模板繼承,block標(biāo)簽定義的元素可在衍生模板中修改htmlviewplaincopy1. <html>2. <head>3. %blockhead%4. <title>%blocktitle%endblock%-MyApplication<

15、/title>5. %endblock%6. </head>7. <body>8. %blockbody%9. %endblock%10. </body>11. </html>extends指令聲明這個(gè)模板衍生自base.html。在extends指令之后,基模板中的3個(gè)塊被重新定義,模板引擎會(huì)將其插入適當(dāng)?shù)奈恢?。注意新定義的head塊,在基模板中其內(nèi)容不是空的,所以使用super()獲取原來的內(nèi)容(向已經(jīng)有內(nèi)容的塊中添加新內(nèi)容)。htmlviewplaincopy1. %extends"base.html"%2. %b

16、locktitle%Index%endblock%3. %blockhead%4. super()5. <style>6. </style>7. %endblock%8. %blockbody%9. <h1>Hello,World!</h1>10. %endblock%使用Flask-BootstrapBootstrap是客戶端框架,因此不會(huì)直接涉及服務(wù)器。服務(wù)器需要做的只是提供引用了Bootstrap層疊樣式表(CSS)和JavaScript文件的HTML響應(yīng),并在HTML、CSS和JavaScript代碼中實(shí)例化所需組件。這些操作最理想的執(zhí)行

17、場(chǎng)所就是模板。Flask-Bootstrap基模板中定義的塊:doc,head,title,styles,body,navbar,content,scriptsBootstrap官方文檔CDN本地加速:修改Base.html,引用本地的css文件,里面元素跟Bootstrap重名的,則會(huì)覆蓋官方里相同元素htmlviewplaincopy1. %blockhead%2. super()3. <linkrel="shortcuticon"href="url_for('static',filename='favicon.ico')

18、"type="image/x-icon">4. <linkrel="icon"href="url_for('static',filename='favicon.ico')"type="image/x-icon">5.<linkrel="stylesheethref="/6. <linkrel="stylesheet"href="/7. %endblock%8.9. %blockscripts%1

19、0. super()11. <scriptsrc="/12. <scriptsrc="/13. moment.include_moment()14. moment.lang("zh-CN")15. %endblock%自定義錯(cuò)誤頁面pythonviewplaincopy1. app.errorhandler(404)2. defpage_not_found(e):3. returnrender_template('404.html'),404url_for()鏈接輔助函數(shù)使用url_for()生成動(dòng)態(tài)地址時(shí),將動(dòng)態(tài)部分作為關(guān)鍵

20、字參數(shù)傳入。例如,url_for('user',name='john',_external=True)的返回結(jié)果是http:/localhost:5000/user/john使用Flask-Moment本地化日期和時(shí)間。查閱文檔htmlviewplaincopy1. %blockscripts%2. super()3. moment.include_moment()4. <!-使用中文,默認(rèn)是英語的->5. moment.lang("zh-CN")6. %endblock%4WebForm表單app.config字典可用來存儲(chǔ)框架

21、、擴(kuò)展和程序本身的配置變量。使用標(biāo)準(zhǔn)的字典句法就能把配置值添加到app.config對(duì)象中。這個(gè)對(duì)象還提供了一些方法,可以從文件或環(huán)境中導(dǎo)入配置值。Form基類由Flask-WTF擴(kuò)展定義,所以從flask.ext.wtf中導(dǎo)入。字段和驗(yàn)證函數(shù)可以直接從WTForms包中導(dǎo)入。pythonviewplaincopy1. fromflask_wtfimportForm2. fromwtformsimportStringField,SubmitField3. fromwtforms.validatorsimportDataRequired4. classNameForm(Form):5. name

22、=StringField('Whatisyourname?',validators=DataRequired()6. submit=SubmitField('Submit')WTForms支持的HTML標(biāo)準(zhǔn)字段:StringField,TextAreaField,PasswordField。WTForms內(nèi)建的驗(yàn)證函數(shù):Email,DataRequired.Placeholder提示:pythonviewplaincopy1.password=PasswordField('Password',validators=DataRequired(),r

23、ender_kw="placeholder":u"密碼”)重定向和用戶會(huì)話刷新頁面后會(huì)再次提交表單。大多數(shù)情況下,這并不是理想的處理方式。很多用戶都不理解瀏覽器發(fā)出的這個(gè)警告?;谶@個(gè)原因,最好別讓W(xué)eb程序把POST請(qǐng)求作為瀏覽器發(fā)送的最后一個(gè)請(qǐng)求。這個(gè)技巧稱為Post/重定向/Get模式。pythonviewplaincopy1. app.route('/',methods='GET','POST')2. defindex():3.form=NameForm()4.ifform.validate_on_submi

24、t():5. session'name'=.data6. returnredirect(url_for('index')7. returnrender_template('index.html',form=form,name=session.get('name')使用get()獲取字典中鍵對(duì)應(yīng)的值以避免未找到鍵的異常情況,因?yàn)閷?duì)于不存在的鍵,get()會(huì)返回默認(rèn)值None。Flash消息僅調(diào)用flash()函數(shù)并不能把消息顯示出來,程序使用的模板要渲染這些消息。最好在base.html中渲染Flash消息,因?yàn)檫@

25、樣所有頁面都能使用這些消息。Flask把get_flashed_messages()函數(shù)開放給模板,用來獲取并渲染消息5數(shù)據(jù)庫(kù)2016-6-9使用SQL還是NoSQLSQL數(shù)據(jù)庫(kù)擅于用高效且緊湊的形式存儲(chǔ)結(jié)構(gòu)化數(shù)據(jù)。這種數(shù)據(jù)庫(kù)需要花費(fèi)大量精力保證數(shù)據(jù)的一致性。NoSQL數(shù)據(jù)庫(kù)放寬了對(duì)這種一致性的要求,從而獲得性能上的優(yōu)勢(shì)。MySQLQ&A:安裝MySQLinWindows報(bào)錯(cuò):需要預(yù)先把WindowsDefender打開,或者configuremysqlserver時(shí),不要勾選"WindowsFirewall”可能要先安裝:MicrosoftVisualC+Compilerf

26、orPython2.7本地安裝MySQLdb:pipinstallmysql-pythonWindow764位下安裝可能還會(huì)報(bào)cl.exe錯(cuò)workaround:先condainstallmysql-python,再手動(dòng)復(fù)制以下目錄及文件至UvenvLibSite-packages下:Anaconda2Libsite-packagesMySQLdbAnaconda2Libsite-packagesMySQL_python-1.2.5.dist-infoAnaconda2Libsite-packages_mysql*MySQL創(chuàng)建connection之后,還需要?jiǎng)?chuàng)建"schema”-對(duì)

27、應(yīng)SQLAlchemy里的adatabase”MySQLdb中文亂碼的處理:conn=MySQLdb.connect(host='localhost',user='root',passwd='XXX',db='app_englishgo',charset='utf8')顯示:title.encode('gbk')接收輸入:unicode(request.form'title')SQLAlchemy和MongoEngine:數(shù)據(jù)庫(kù)抽象層代碼包(ORM、ODM),你可以使用這些抽象包直接

28、處理高等級(jí)的Python對(duì)象,而不用處理如表、文檔或查詢語言此類的數(shù)據(jù)庫(kù)實(shí)體。使用Flask-SQLAlchemy管理數(shù)據(jù)庫(kù)MySQLmysql:username:passwordhostname:port/databaseSQLite(Windows)sqlite:/c:/absolute/path/to/databaseRelationship關(guān)系型數(shù)據(jù)庫(kù)pythonviewplaincopy1.classRole(db.Model):2.#.3. users=db.relationship('User',backref='role')#面向?qū)ο笠暯?. c

29、lassUser(db.Model):5. #.6. role_id=db.Column(db.Integer,db.ForeignKey('roles.id')#定義外鍵SQLAlchemy完整的命令、過濾器、查詢執(zhí)行列表參見SQLAlchemy文檔SQLAlchemyengine設(shè)置編碼,防止中文亂碼:pythonviewplaincopy1. engine=create_engine('sqlite:/C:Temptestsqlalchemy.db',encoding='utf8',convert_unicode=True,echo=Tru

30、e)2. #echo:顯示出內(nèi)部過程及SQL語句。debug或?qū)W習(xí)時(shí)打開3. #encoding:防止亂碼pythonviewplaincopy1. 'mysql:/uid:pwdlocalhost/mydb?charset=utf8'集成Pythonshell每次啟動(dòng)shell會(huì)話都要導(dǎo)入數(shù)據(jù)庫(kù)實(shí)例和模型。為避免重復(fù)導(dǎo)入,我們可以做些配置,讓Flask-Script的shell命令自動(dòng)導(dǎo)入特定的對(duì)象。為shell命令注冊(cè)一個(gè)make_context回調(diào)函數(shù)新數(shù)據(jù)庫(kù)遷移flask-migrate由于模型中經(jīng)常會(huì)新加一行或幾行column(比如用來保存賬戶的確認(rèn)狀態(tài)),此時(shí)要修改

31、models.py,并執(zhí)行一次新數(shù)據(jù)庫(kù)遷移MySQLWorkbench自動(dòng)產(chǎn)生EER,可以清楚地看到各個(gè)表格之間關(guān)系:一對(duì)多Foreign_Key、Index等1) config.py:pythonviewplaincopy1. classDevelopmentConfig(Config):2. DEBUG=True3. #SQLALCHEMY_DATABASE_URI=os.environ.get('DEV_DATABASE_URL')or'sqlite:/'+os.path.join(basedir,'data-dev.sqlite')4.

32、SQLALCHEMY_DATABASE_URI='mysql:/USER:PASSWORDlocalhost:3306/flaskr'2) pythonmanage.pydeploy選擇connection->database3) MySQLWorkbench:Database->ReverseEngineer->->一路NextOpastsidlNT(ll)bodyItKTtimestampDATETIMErolejdINTCll)authorjdIMT(ll)bodV-htrlTbXTpassword_hashVARCHARC128)confirme

33、dTINYINr(i)aboutmeTEXT1stseenDATETIMElocationVAFLCHAR(64)memhersinceDATETIMEidlNT(ll)nameVAR£HAR(64)H-bodyTEKTbody_htmlTEXTPRIMARYtimestampDATETIMEixusersusemaneixusersemailroleidpostjdIMT(ll)usernameV7RCHAR.(6;_usersaval3r_ha;hMARCH岷02)T"lcomments一干IXAdiscedTINYINT(l)authorJdINTfll>icH

34、isrrii)VLCHAR(64)M-H-rolesidlMT(ll)nameVARCHAR(64)defeultTINYINTfl)permiionsINT(ll)PRIMARYnameijrolesdefault二IalembicversioniersionnumVARGH.AR(32)followstimestampDATFTIMEPRIMARYlbIowedid6E-mail使用Flask-Mail提供電子郵件支持pythonviewplaincopy1. app.config'MAIL_SERVER'=''2. app.config'MAIL_

35、PORT'=253. app.config'MAIL_USE_TLS'=True4. app.config'MAIL_USERNAME'=os.environ.get('MAIL_USERNAME')5. app.config'MAIL_PASSWORD'=os.environ.get('MAIL_PASSWORD')6. app.config'FLASKY_MAIL_SUBJECT_PREFIX'='Flasky'7. app.config'FLASKY_MAIL_

36、SENDER'='FlaskyAdmin<flasky>8. app.config'FLASKYADMIN'=os.environ.get('FLASKYADMIN')10. mail=Mail(app)11.12. defsendmail(mail):13. msg=Message('testsubject',sender='ezhqing',recipients='XXX')14. msg.body='textbody'15. msg.html='<b&

37、gt;HTML</b>body'16. withapp.app_context():17. mail.send(msg)千萬不要把賬戶密令直接寫入腳本,特別是當(dāng)你計(jì)劃開源自己的作品時(shí)。讓腳本從本機(jī)環(huán)境中導(dǎo)入敏感信息Windows用戶可按照下面的方式設(shè)定環(huán)境變量:plainviewplaincopy1. (venv)$setMAIL_USERNAME=<yourmailusername>2. (venv)$setMAIL_PASSWORD=<mailpassword>所有的在cmd命令行下對(duì)環(huán)境變量的修改只對(duì)當(dāng)前窗口有效,不是永久性的修改。也就是說當(dāng)關(guān)

38、閉此cmd命令行窗口后,將不再起作用。永久性修改環(huán)境變量的方法有兩種:一種是直接修改注冊(cè)表(overkillpythonscript),另一種是通過我的電腦->屬性-高級(jí),來設(shè)置系統(tǒng)的環(huán)境變量異步發(fā)送電子郵件為了避免處理請(qǐng)求過程中不必要的延遲,我們可以把發(fā)送電子郵件的函數(shù)移到后臺(tái)線程(Threading)中很多Flask擴(kuò)展都假設(shè)已經(jīng)存在激活的程序上下文和請(qǐng)求上下文。Flask-Mail中的send()函數(shù)使用current_app,因此必須激活程序上下文。不過,在不同線程中執(zhí)行mail.send()函數(shù)時(shí),程序上下文要使用app.app_context()人工創(chuàng)建。7大型程序的結(jié)構(gòu)項(xiàng)目

39、結(jié)構(gòu)plainviewplaincopy1. |-flasky2. |-app/Flask程序一般都保存在名為app的程序包中3. ktemplates/templates和static文件夾是程序包的一部分4. 卜static/5. |-main/程序包中創(chuàng)建了一個(gè)子包,用于保存藍(lán)本。/main/_init_.py腳本的末尾導(dǎo)入views.py&errors.py,避免循環(huán)導(dǎo)入依賴6. |-_init_.py程序工廠函數(shù)create_app(),注冊(cè)藍(lán)本7. kerrors.py錯(cuò)誤處理路由.注冊(cè)程序全局的錯(cuò)誤處理程序,必須使用app_errorhandler8. |-forms.p

40、y表單對(duì)象9. |-views.py路由。藍(lán)本中的全部端點(diǎn)會(huì)加上一個(gè)命名空間,如url_for('main.index')10. |-_init_.py11. |-email.py電子郵件支持函數(shù)12. |-models.py數(shù)據(jù)庫(kù)模型13. kmigrations/數(shù)據(jù)庫(kù)遷移腳本14. |-tests/單元測(cè)試15. |-_init_.py文件可以為空,因?yàn)閡nittest包會(huì)掃描所有模塊并查找測(cè)試16. |-test*.py17. |-venv/虛擬環(huán)境18. |-requirements.txt列出了所有依賴包,便于在其他電腦中重新生成相同的虛擬環(huán)境19. |-confi

41、g.py存儲(chǔ)配置。開發(fā)、測(cè)試和生產(chǎn)環(huán)境要使用不同的數(shù)據(jù)庫(kù)20. |-manage.py用于啟動(dòng)程序以及其他的程序任務(wù)requirements.txt文件,用于記錄所有依賴包及其精確的版本號(hào)。以便要在另一臺(tái)電腦上重新生成虛擬環(huán)境創(chuàng)建:(venv)$pipfreeze>requirements.txt恢復(fù):(venv)$pipinstall-rrequirements.txt重組后的程序和單腳本版本使用不同的數(shù)據(jù)庫(kù),可使用如下命令創(chuàng)建數(shù)據(jù)表或者升級(jí)到最新修訂版本:(venv)$pythonmanage.pydbupgrade8用戶認(rèn)證Flask的認(rèn)證擴(kuò)展Flask-Login:管理已登錄用戶

42、的用戶會(huì)話。Werkzeug:計(jì)算密碼散列值并進(jìn)行核對(duì)。itsdangerous:生成并核對(duì)加密安全令牌。創(chuàng)建認(rèn)證藍(lán)本對(duì)于不同的程序功能,我們要使用不同的藍(lán)本(main,auth),這是保持代碼整齊有序的好方法因?yàn)镕lask認(rèn)為模板的路徑是相對(duì)于程序模板文件夾而言的。為避免與main藍(lán)本和后續(xù)添加的藍(lán)本發(fā)生模板命名沖突,可以把藍(lán)本使用的模板保存在單獨(dú)的文件夾中使用Flask-Login認(rèn)證用戶LoginManager對(duì)象的session_protection屬性可以設(shè)為None、'basic'或'strong',以提供不同的安全等級(jí)防止用戶會(huì)話遭篡改。設(shè)為

43、9;strong'時(shí),F(xiàn)lask-Login會(huì)記錄客戶端IP地址和瀏覽器的用戶代理信息,如果發(fā)現(xiàn)異動(dòng)就登出用戶。為了保護(hù)路由只讓認(rèn)證用戶訪問,F(xiàn)lask-Login提供了一個(gè)login_required修飾器current_user由Flask-Login定義,且在視圖函數(shù)和模板中自動(dòng)可用模板中加入用戶登錄后白信息和提示效果base.html:TClocalhost:5000%網(wǎng)=1FlaskyHomeLogOul)ohnHello,john!1. <ulclass="navnavbar-navnavbar-right">2. %ifcurrent_us

44、er.is_authenticated%3. <li><ahref="url_for('auth.logout')"title="郵件current_user.email:9+'.'">LogOutcurrent_user.username</a></li>4. %else%5. <li><ahref="url_for('auth.login')">LogIn</a></li>6. %endi

45、f%7. </ul>按照第4章介紹的“Post/重定向/Get模式",Login的POST請(qǐng)求最后也做了重定向,不過目標(biāo)URL有兩種可能。用戶訪問未授權(quán)的URL時(shí)會(huì)顯示登錄表單,F(xiàn)lask-Login會(huì)把原地址保存在查詢字符串的next參數(shù)中,這個(gè)參數(shù)可從request.args字典中讀取。如果查詢字符串中沒有next參數(shù),則重定向到首頁app/auth/views.pypythonviewplaincopy1. user=User.query.filter_by(email=form.email.data).first()2. ifuserisnotNoneanduse

46、r.verify_password(form.password.data):3. login_user(user,form.remember_me.data)4. returnredirect(request.args.get('next')orurl_for('main.index')用戶注冊(cè)表單app/auth/forms.py這個(gè)表單使用WTForms提供的Regexp驗(yàn)證函數(shù),確保username字段只包含字母、數(shù)字、下劃線和點(diǎn)號(hào)。密碼要輸入兩次。此時(shí)要驗(yàn)證兩個(gè)密碼字段中的值是否一致,這種驗(yàn)證可使用WTForms提供的另一驗(yàn)證函數(shù)實(shí)現(xiàn),即EqualTo如

47、果表單類中定義了以validate_開頭且后面跟著字段名的方法,這個(gè)方法就和常規(guī)的驗(yàn)證函數(shù)一起調(diào)用發(fā)送確認(rèn)郵件使用itsdangerous生成確認(rèn)令牌pythonviewplaincopy1. >>>fromitsdangerousimportTimedJSONWebSignatureSerializerasSerializer2. >>>s=Serializer(app.config'SECRET_KEY',expires_in=3600)3. >>>token=s.dumps('confirm':23)4

48、. >>>token5.'eyJhbGciOiJIUzI1NiIsImV4cCI6MTM4MTcxODU1OCwiaWF0IjoxMzgxNzE0OTU4fQ.ey.'6. >>>data=s.loads(token)7. >>>data8. u'confirm':23對(duì)藍(lán)本來說,before_request鉤子只能應(yīng)用到屬于藍(lán)本的請(qǐng)求上。若想在藍(lán)本中使用針對(duì)程序全局請(qǐng)求的鉤子,必須使用before_app_request修飾器9. UserRole角色2016-6-10角色在數(shù)據(jù)庫(kù)中的表示賦予角色角色驗(yàn)證1

49、0. UserProfile資料2016-6-10用戶資料頁面htmlviewplaincopy<-Cjlocalhost:SOOD/user/johnAccountChangePasswordChangeEmailLogOutFlaskyHomeProfilejohnjack押rmFmmNanjing.ChinaHeamiriigFlaskMembe-rsince0/1D.i'2Dl6_Lastseenafewsecondsago.EditProfile資料編輯器用戶頭像國(guó)內(nèi)被墻,改用其它方法:靜態(tài)jpg頭像目錄:c:gitflaskyappstaticavatar001.jp

50、gXXX.jpgbase.html:htmlviewplaincopy1. <liclass="dropdown">2. <ahref="#"class="dropdown-toggle"data-toggle="dropdown">3. <imgheight="24px"src="url_for('static',filename='avatar/')current_user.avatar_hash">mo

51、dels.py:pythonviewplaincopy1. defgravatar(self,size=100,default='identicon',rating='g'):2. importrandom3. return'%.3d.jpg'%random.randint(1,XXX)user.html:htmlviewplaincopy1. <divclass="page-header">2. <imgclass="img-roundedprofile-thumbnail"src=&q

52、uot;url_for('static',filename='avatar/')current_user.avatar_hash"">_posts.html:htmlviewplaincopy1. <liclass="post">2. <divclass="post-thumbnail">3. <ahref="url_for('.user',username=post.author.username)">4. <imgh

53、eight="40px"class="img-roundedprofile-thumbnail"src="url_for('static',filename='avatar/')post.author.avatar_hash">_commments.html:htmlviewplaincopy1. <divclass="comment-thumbnail">2. <ahref="url_for('.user',username=com

54、ment.author.username)">3. <imgheight="40px'class="img-roundedprofile-thumbnail"src="url_for('static',filename='avatar/')post.author.avatar_hash">效果:Followerskimbtrly872daysagoMorbinonlectus.Fuseelacuspurus,aliquetat.feugiatnon,pretiumquislec

55、tus.Morbivestibulum.velitidpretiumiaculis.diameratfermentumjusto,neccondimentumnequesapienplaceratante.Nullamvarius.EdiitAdminIPermalinkI1CominentsdianaG32daysageMaecenasIe。odio,condimentumidLluctusnecmolestiesedjustoEditAdhimIPermalinkI2Coniirientskathryn782SysagoDoneequksorciegetorcivemculacondime

56、ntunnincargueNuNaacenlmEditAdminIPermalinkI1Comnients擴(kuò)展TODO:加入性別、用戶自選頭像。11Blogarticles博客文章2016-6-12實(shí)現(xiàn)功能,即允許用戶閱讀、撰寫博客文章。本章新技術(shù):重用模板、分頁顯示長(zhǎng)列表以及處理富文本。生成虛擬信息用于測(cè)試,其中功能相對(duì)完善的是ForgeryPypythonviewplaincopy1. pythonmanage.pyshell2. >>>User.generate_fake()3. >>>Post.generate_fake(200)添加分頁導(dǎo)航pagi

57、nate()方法的返回值是一個(gè)Pagination類對(duì)象,這個(gè)類在Flask-SQLAlchemy中定義。這個(gè)對(duì)象包含很多屬性,用于在模板中生成分頁鏈接使用Markdown和Flask-PageDown支持富文本文章?PageDown:使用JavaScript實(shí)現(xiàn)的客戶端Markdown至UHTML的轉(zhuǎn)換程序。?Flask-PageDown:為Flask包裝的PageDown,把PageDown集成至UFlask-WTF表單中。?Markdown:使用Python實(shí)現(xiàn)的服務(wù)器端Markdown至UHTML的轉(zhuǎn)換程序。?Bleach:使用Python實(shí)現(xiàn)的HTML清理器。博客文章的固定鏈接博客文

58、章編輯器12followers關(guān)注者2016-6-12再論數(shù)據(jù)庫(kù)關(guān)系一對(duì)多關(guān)系:是最常用的關(guān)系類型,它把一個(gè)記錄和一組相關(guān)的記錄聯(lián)系在一起。實(shí)現(xiàn)這種關(guān)系時(shí),要在“多”這一側(cè)加入一個(gè)外鍵,指向“一”這一側(cè)聯(lián)接的記錄。多對(duì)多關(guān)系:這種問題的解決方法是添加第三張表,這個(gè)表稱為關(guān)聯(lián)表。多對(duì)多關(guān)系可以分解成原表和關(guān)聯(lián)表之間的兩個(gè)一對(duì)多關(guān)系若想顯示所關(guān)注用戶發(fā)布的所有文章,第一步顯然先要獲取這些用戶,然后獲取各用戶的文章,再按一定順序排列,寫入單獨(dú)列表。可是這種方式的伸縮性不好,隨著數(shù)據(jù)庫(kù)不斷變大,生成這個(gè)列表的工作量也不斷增長(zhǎng),而且分頁等操作也無法高效率完成。獲取博客文章的高效方式是只用一次查詢。完成這

59、個(gè)操作的數(shù)據(jù)庫(kù)操作稱為聯(lián)結(jié)。聯(lián)結(jié)操作用到兩個(gè)或更多的數(shù)據(jù)表,在其中查找滿足指定條件的記錄組合,再把記錄組合插入一個(gè)臨時(shí)表中,這個(gè)臨時(shí)表就是聯(lián)結(jié)查詢的結(jié)果。創(chuàng)建函數(shù)更新數(shù)據(jù)庫(kù)這一技術(shù)經(jīng)常用來更新已部署的程序,因?yàn)檫\(yùn)行腳本更新比手動(dòng)更新數(shù)據(jù)庫(kù)更少出錯(cuò)。13 Usercomments評(píng)論評(píng)論屬于某篇博客文章,因此定義了一個(gè)從posts表到comments表的一對(duì)多關(guān)系。使用這個(gè)關(guān)系可以獲取某篇特定博客文章的評(píng)論列表。comments表還和users表之間有一對(duì)多關(guān)系。通過這個(gè)關(guān)系可以獲取用戶發(fā)表的所有評(píng)論,還能間接知道用戶發(fā)表了多少篇評(píng)論管理評(píng)論,我們要在導(dǎo)航條中添加一個(gè)鏈接,具有權(quán)限的用戶才能看到。14 RIA(API,REST)2016-6-12資源就是一切資源是REST架構(gòu)方式的核心概念。在REST架構(gòu)中,資源是程序中你要著重關(guān)注的

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(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ì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論