flask tutorial = make a blog :) flask 搭建博客系统从零开始!
please follow the tutorial from the official site :)?
http://flask.pocoo.org/docs/
You could download the zipped file from this site : 下載離線版doc ,將更加方便查看。
You can download the documentation in other formats as well:
- as PDF
- as ePub
- as .mobi
- as zipped HTML
?
要搭建博客,就需要至少有幾個工具。
1、搭建博客的工具——————python,建議搭配virtualenv(這點是從pyramid 框架中學來的? :) ),這樣將非常有利于后來的發展,好搭配各種環境庫,這樣也容易打包
2、需要知道的程序語言——————python, html, javascript, 一些計算機方面的常識
3、零活一點,多查閱docs,不會的要去用google,irc等等
Please follow this tutorial : http://flask.pocoo.org/docs/tutorial/#tutorial
這里我使用的是linuxmint 13 操作系統。總體來說非常好用。
下面是具體實現步驟
?
一、安裝virtualenv
sudo apt-get install python-virtualenv -y二、創建環境
virtualenv env_27_flask --no-site-packages在當錢目錄下創建一個文件夾 env_27_flask , 是沒有網站原包的虛擬環境,這樣的很干凈。(pyramid學來的 )
三、在虛擬環境中安裝flask
cd env_27_flask ./bin/pip install flask # to install flask in the virtualenv folder等待一段時間后,會自動下載一些依賴包。環境里面就安裝了flask。 (pip 和 easy_install 區別,前者官方,后者比較隨意,詳情google之 ,plz)
四、創建一個flask項目
mkdir -p ./flaskr/{static, templates}說明 目錄
./flaskr 項目總目錄
./flask/static 用于存放靜態頁面的目錄
./flask/templates 用于存放網頁模板的目錄
五、構建數據表(這是為未來保存博客內容考慮的)
如下圖:
代碼在:
drop table if exists entries; create table entries(id integer primary key autoincrement,title text not null,text text not null );準備使用的數據庫產品是sqlite3, 當然類似的數據庫產品MySQL, PostGRESQL也都是可行的。
?
保存在 ./flaskr 目錄下
?
六、新建app
詳情:http://flask.pocoo.org/docs/tutorial/setup/#step-2-application-setup-code
1)新建一個 flask.py 的文件,其引用的模塊內容應該有
?
from flask import Flask, request, session, g, redirect, url_for, \abort, render_template, flash解釋
Flask 用于做新建app的一個類。能生成一個新得app對象。 請看下面的代碼例子
request 是網頁上表單傳來的GET 或者 POST 的請求。 可以用 request.method (這個變量有兩個選項,一個是POST,一個是GET,在請求發送的時候都已經在原HTML表單中定義了), request.form['title'], request.form['text'] (意思是來自表單中 html 標簽 name='title' 所提交的內容)
session 用來和cookie配合,判斷用戶是否登錄的。這個東西是個好東西阿。
?
g 是在用來html頁面訪問URL, 發送一些GET、POST請求的時候, 用來從數據庫里面提取數據,每次都在before request (建立數據庫會話), 和 after request(關閉數據庫會話) 自動發生的。 具體結合 裝飾器 @app.before_request @app.after_request 來使用的。請看下面的實例代碼
?
redirect 將會返回一個自動跳轉頁面命令,在裝飾器 @app.route('/path/to', methods=['POST或者GET']) 的作用下,將返回一個html自動跳轉頁面命令,也就是說,當用戶點擊了含有裝飾器為 @app.route('/path/to', methods=['POST或者GET']) 其 最后有 return redict(“一個URL-B”)的鏈接, 將會自動轉到 www.xxxx.com/URL-B? 的鏈接頁面上。
?
url_for 一般配合 redirect 使用。url_for 的更多內容請參考: http://flask.pocoo.org/docs/quickstart/#url-building
>>> from flask import Flask, url_for >>> app = Flask(__name__) >>> @app.route('/') ... def index(): pass ... >>> @app.route('/login') ... def login(): pass ... >>> @app.route('/user/<username>') ... def profile(username): pass ... >>> with app.test_request_context(): ... print url_for('index') ... print url_for('login') ... print url_for('login', next='/') ... print url_for('profile', username='John Doe') ... / /login /login?next=/ /user/John%20Doeurl_for 和 redirect 配合使用后,就會重新定向到一個route。 而被這個route裝飾的程序,就會返回其應有的東西。具體請看下面的詳盡代碼案例。
?
abort 故名思意,請參考http://flask.pocoo.org/docs/api/?highlight=abort#flask.abort
?
render_template, 會將參數導入到一個template中,template有模板引擎標記語言。這里flask默認的是jinja2. 詳情看下面的代碼
?
2) 新建配置環境內容,需要大寫!
請看下面的內容解釋
?其中app.config.from_object(__name__)
和 app.config.from_envvar('FLASKER_SETTINGS', silent=True)
相互補充,各有各的好處。上圖也說了,當有大量的不同的配置的時候,第二者就比較科學方便了。
更多關于app 環境配置的內容,請訪問:http://flask.pocoo.org/docs/tutorial/setup/#step-2-application-setup-code
3)、定義建立到數據庫的方法
?
這樣還不完整,因為,還沒有建立數據庫表格內容。所以,還需要create database. 上面僅僅是為了未來方便。
4)新建數據表內容
http://flask.pocoo.org/docs/tutorial/dbinit/#step-3-creating-the-database
這個鏈接內的內容很詳細,這里不做贅述了。簡單的說就是數據庫初始化。
?簡單的使用方法如下,這樣的方法是新做一個表,按照schema結構:
sqlite3 /tmp/flaskr.db < schema.sql
5)處理請求與數據庫之間的鏈接
Request Database Connections
http://flask.pocoo.org/docs/tutorial/dbcon/#step-4-request-database-connections
在這里將體現前面引入模塊 from flask import g 的妙處
flask將請求分為兩種,于是用兩種裝飾器,
一種@app.before_request??????? 這種是為了在獲得請求訪問數據庫內容前,事先做好與數據庫的連接準備
另外一種@app.after_request?????? 這種是在和數據庫完成數據訪問后,自動關閉與數據庫的連接,這樣將節省資源,必須的
6)添加http URL訪問路徑 view functions
http://flask.pocoo.org/docs/tutorial/views/#step-5-the-view-functions
?
[1] 關于路徑和模板直接的關系
在這個例子中,將會有
比如說路徑 “/” 會去訪問數據庫內容。由于前面的from flask import g? 的杰出貢獻,我們只管連接獲取就好了,不用去考慮新建數據庫連接或者關閉數據庫連接了。省了很多代碼和腦細胞。
對代碼
@app.route('/') def show_entries():cur = g.db.execute('select title, text from entries order by id desc')entries = [dict(title=row[0], text=row[1]) for row in cur.fetchall()]return render_template('show_entries.html', entries=entries)?
中的
render_template('show_entries.html', entries = entries) # 這里把上面定義的方法的entries 變量導入到 模板 show_entries.html? 中的entries 變量中了。 注意,這里左邊的entries是show_entries.html 中的,右邊的entries 是該方法中的變量。
?
[2] 增加新的分錄
http://flask.pocoo.org/docs/tutorial/views/#add-new-entry
這里會有體現session的用法,只有當session.get('logged_in') 存在(即用戶登錄了)的時候才能程序往下進行。不然這里就要體現 abort(401)?? (來自 from flask import abort)的功力了。
?
[3] 處理登錄和登出 login and logout
[3.1] login
這個是要和網頁模板之間緊密相連的,jinja2 模板引擎里面有個很好的選項是 extend, 在下面我將會細講。
上面代碼就是說明,兩個問題
????????????????????????????? 1.當以這種方式,上圖是POST和GET 訪問URL?? /login?? 的時候,會指向 login.html 頁面
????????????????????????????? 2.會將一個變量傳遞給html模板 error = error? , 而error的內容具體有里面POST或者GET的內容是否跟應用匹配而決定的
????????????? 就這么兩個事兒。
上面的圖中代碼有 flash? 真的,這個和jinja2配合的很不錯。jinja2模板引擎里面有一個命令叫
get_flashed_messages()
比較人性化。具體請結合事成的blog自我感覺。
?
[3.2] logout
將 session.pop('logged_in', None)?? 干掉了'logged_in' 這個元素,然后又flash了一下。重新指向方法為'show_entries'的URL頁面。
也就是說沒登錄上,可以看博客。登錄上了不僅可以看博客,還有一個博客添加內容。
觀察代碼后,綜合分析一下
logout 的狀態是 沒有登錄, 重新定向到 url_for('show_entries')
login?? 的狀態是 已經登錄 分兩個 1、登錄成功 也是重新定向到 url_for('show_entries')? 2、沒有登錄成功,還是一直返回 render_template('login.html', error=error)
?
那么,既然login, logout 兩者狀態不同,但是都能返回到URL url_for('show_entries') ,所以,一定在模板 'show_entries' 中,有對login 與否的 session有判斷。不然login后為什么會有添加博客的form表,而logout的沒有?!
?
查看一下模板show_entries源碼,如下幾行就是造成是否有權利寫博客的原因。
不出所料呀!
不出所料吧。
看看如實效果圖
下面是 沒有登錄的 或者是 logout狀態后的
上圖不能自由填寫博客內容,只能瀏覽博客。
?
下面的圖片是登錄后的
不同點就在于 login 之后的,就可以填寫博客內容啦。
?
[4]、網頁模板
http://flask.pocoo.org/docs/tutorial/templates/#step-6-the-templates
上面是為了演示所以先展示了做好的圖片。這里將介紹為什么是這樣的模板。
不同于 Markup 或者 |saft? 過濾器 一般我會這樣用
from cgi import escape
return escape(a)?????? # 這里是將本來是HTML格式的a, 以反義符號(就是不轉換HTML代碼, 詳情請看?http://www.w3school.com.cn/html/html_entities.asp )
?
用法都是一樣的
<!doctype html> <title>Flaskr</title> <link rel=stylesheet type=text/css href="{{ url_for('static', filename='style.css') }}"> <div class=page><h1>Flaskr</h1><div class=metanav>{% if not session.logged_in %}<a href="{{ url_for('login') }}">log in</a>{% else %}<a href="{{ url_for('logout') }}">log out</a>{% endif %}</div>{% for message in get_flashed_messages() %}<div class=flash>{{ message }}</div>{% endfor %}{% block body %}{% endblock %} </div>?
?
上面我們有提過關于session.logged_in 的判斷機制問題。這里在模板 show_entries.html 中又會體現。
{% extends "layout.html" %} {% block body %}<h2>Login</h2>{% if error %}<p class=error><strong>Error:</strong> {{ error }}{% endif %}<form action="{{ url_for('login') }}" method=post><dl><dt>Username:<dd><input type=text name=username><dt>Password:<dd><input type=password name=password><dd><input type=submit value=Login></dl></form> {% endblock %}?
? 上面也說過,jinja2的模板引擎有個好處就是 能繼承 {% extends 'layout.html' %}
? 上面的 show_entries.html 繼承了? layout.html
?????????? login.html 也繼承了 layout.html
????????? 其直面表管就是都有了網頁的上半部分,無論是否登錄還是別的登錄頁面。很科學的呀!
?
[5]、添加樣式表
http://flask.pocoo.org/docs/tutorial/css/#step-7-adding-style
保存到./flaskr/static/style.css 中就okay了
?
[6]、開始測試網站
?以上代碼全部為手工,請在復寫的時候注意不要范低級錯誤。把debug選項打開,將有利于知道哪里出現問題。
使用
#在flaskr目錄下使用 $../bin/python flaskr.py?
http://flask.pocoo.org/docs/tutorial/testing/#bonus-testing-the-application
更多關于flask的網站調試內容,將在這里展示:http://flask.pocoo.org/docs/testing/#testing-flask-applications
?
?
附上自己寫的代碼及英文注釋(重點):
flaskr.py
# all the imports import sqlite3 from flask import Flask, request, session, g, redirect,url_for, abort, render_template, flash# this module is used to auto-closing context session when \ # sql database operation is finished # it has the same function of " xxx.close() " ####################################### # con = sqlite3.connect('census.db') # cur = con.cursor() # cur.execute('CREATE TABLE Density(Region TEXT, Population INTEGER, Area REAL)') # [and lots of SQL operation] # cur.close() # con.close() ####################################### # Please visit http://www.cnblogs.com/spaceship9/archive/2013/04/25/3042870.html ####################################### from contextlib import closing# configuration DATABASE = '/tmp/flaskr.db' DEBUG = True SECRET_KEY = 'development key' USERNAME = 'admin' PASSWORD = 'default'# create our little application :) app= Flask(__name__)# [ Flask basic settings ] # from_object() will look at the given object ( if it's a string it will \ # import it) and then look for all uppercase variables defined there. In our \ # case, the configuration we just wrote a few lines of code above. You can \ # also move that into a separate file # [Note:] Flask has two ways to import configuration files # 1. app.config.from_object(__name__) # 2. app.config.from_envvar('FLASKR_SETTINGS', silent=True) # [In this case] we choose way 1. # Here we see app.config.from_object(__name__)# This will create a environmental variable called FLASKR_SETTINGS to specify \ # a config file to be loaded wich will then override the default values. \ # The silent switch just tells Flask to not complain if no such environment key\ # is set. app.config.from_envvar('FLASKR_SETTINGS', silent=True)# The secret_key is needed to keep the client-side sessions secure. # Choose the key wisely and as hard to guess and complex as possible# [ prepare for database] # *connect db* def connect_db():return sqlite3.connect(app.config['DATABASE']) # [in this case] app.config['DATABASE'] ==> DATABASE = '/tmp/flaskr.db'# *initialize db* def init_db():with closing(connect_db()) as db:with app.open_resource('schema.sql', mode='r') as f:db.cursor().executescript(f.read())db.commit()# [organical solution: request with database for opening and closing ] # organically open database session before request @app.before_request def before_request():g.db = connect_db()# organically close database session after request @app.teardown_request def teardown_request(exception):db = getattr(g,'db',None)if db is not None:db.close()# [the view functions] # *show entries* @app.route('/') def show_entries():cur = g.db.execute('select title, text from entries order by id desc')# you gonna love dict to the utmost :)entries = [ dict(title = row[0], text = row[1]) for row in cur.fetchall()]return render_template('show_entries.html', entries = entries)# *add new entry* @app.route('/add', methods=['POST']) def add_entry():if not session.get('logged_in'):abort(401)g.db.execute('insert into entries (title, text) values (?,?)',[request.form['title'], request.form['text']])g.db.commit()flash('New entry was sucessfully posted')return redirect(url_for('show_entries')) # redirect the URL where is hooked up with # function 'show_entries'# [security note] # Login and logout # *login* @app.route('/login', methods = ['GET', 'POST']) def login():error = Noneif request.method == 'POST':if request.form['username'] != app.config['USERNAME']:error = 'Invalid username'elif request.form['password'] != app.config['PASSWORD']:error = 'Invalid password'else:session['logged_in'] = Trueflash('You were logged in')return redirect(url_for('show_entries'))return render_template('login.html', error = error)# *logout* @app.route('/logout') def logout():session.pop('logged_in',None)flash('You were logged out')return redirect(url_for('show_entries'))if __name__=="__main__":app.run(host='0.0.0.0',debug=True)?
項目目錄文件結構:
其中flashr.pyc 是臨時文件
layout.html~ 是臨時文件,layout.html?? 才是使用的模板。
?
好了,步驟就基本上是這樣的。從0開始,一步一步的就能用flask開發博客了。
以后我會介紹一些關于sqlalchmy 還有 一些別的比如JSON, Ajax, RESTful 等技術使用。這里也mark一下。
?
?
Happy Coding :)
?
轉載于:https://www.cnblogs.com/spaceship9/p/3245597.html
總結
以上是生活随笔為你收集整理的flask tutorial = make a blog :) flask 搭建博客系统从零开始!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 买车的时候要注意哪些事项呢?
- 下一篇: jquery 按钮效果 正常、移上、按下