Flask实战1-轻博客
最近學習了一個很簡單的示例,這里總結一下.
整體文件目錄如下
測試平臺: win10 and deepin15.4
測試環境: Python3.6.x
源碼地址: 鏈接:http://pan.baidu.com/s/1qYwQs7y 密碼:gz6t
一.數據庫
對于這個應用僅一張表就足夠了,而且我們只想支持 SQLite ,所以很簡單。 只要把下面的內容放入一個名為schema.sql的文件,文件置于剛才創建的 flaskr 文件夾中:
drop table if exists entries; create table entries (id integer primary key autoincrement,title string not null,text string not null );創建數據庫(三種方式)
1.sqlite3命令
sqlite3 /tmp/flaskr.db < schema.sql如果沒有安裝sqlite3,那就采用下面方法
2.用函數初始化
from __future__ import with_statement from contextlib import closing#接著我們可以創建一個稱為 init_db 函數,該函數用來初始化數據庫。為此我們可以使用之前定義的 connect_db 函數。 只要在 connect_db 函數下添加這樣的函數:def init_db():with closing(connect_db()) as db:with app.open_resource('schema.sql') as f:db.cursor().executescript(f.read())db.commit()closing()函數允許我們在with塊中保持數據庫連接可用。應用對象的open_resource()方法在其方框外也支持這個功能,因此可以在with塊中直接使用。這個函數從當前位置(你的flaskr 文件夾)中打開一個文件,并且允許你讀取它。我們在這里用它在數據庫連接上執行一個腳本。
當我們連接到數據庫時會得到一個數據庫連接對象(這里命名它為 db),這個對象提供給我們一個數據庫指針。指針上有一個可以執行完整腳本的方法。最后我們不顯式地提交更改, SQLite 3 或者其它事務數據庫不會這么做。
現在可以在 Python shell 里創建數據庫,導入并調用剛才的函數:
>>> from flaskr import init_db >>> init_db()我在測試時這里出現一點問題,所以在win10下采用了第三種方式
3.可視化工具直接建表
工具:sqlitebrowser
下載地址:http://sqlitebrowser.org/
關于sqlite3我自己的簡單總結:
http://blog.csdn.net/co_zy/article/details/77045039
請求數據庫連接
現在我們知道了怎樣建立數據庫連接以及在腳本中使用這些連接,但是我們如何能優雅地在請求中這么做?
所有我們的函數中需要數據庫連接,因此在請求之前初始化它們,在請求結束后自動關閉他們就很有意義。
Flask 允許我們使用before_request(),after_request()和 teardown_request()裝飾器來實現這個功能:
@app.before_request def before_request():g.db = connect_db()@app.teardown_request def teardown_request(exception):g.db.close()二.視圖函數
顯示條目
這個視圖顯示所有存儲在數據庫中的條目。它監聽著應用的根地址以及將會從數據庫中查詢標題和內容。id值最大的條目(最新的條目)將在最前面。從游標返回的行是按select語句中聲明的列組織的元組。對于像我們這樣的小應用是足夠的,但是你可能要把它們轉換成字典,如果你對如何轉換成字典感興趣的話,請查閱簡化查詢例子。
視圖函數將會把條目作為字典傳入show_entries.html模版并返回渲染結果:
@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)添加新條目
這個視圖允許登錄的用戶添加新的條目。它只回應POST請求,實際的表單是顯示在show_entries頁面。如果工作正常的話,我們用flash()向下一個請求閃現一條信息并且跳轉回show_entries頁:
@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 successfully posted')return redirect(url_for('show_entries'))登錄和注銷
這些函數是用于用戶登錄以及注銷。登錄時依據在配置中的值檢查用戶名和密碼并且在會話中設置logged_in鍵值。如果用戶成功登錄,logged_in鍵值被設置成True,并跳轉回show_entries頁。此外,會有消息閃現來提示用戶登入成功。
如果發生錯誤,模板會通知,并提示重新登錄:
@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)另一方面,注銷函數從會話中移除了logged_in鍵值。這里我們使用一個大絕招:如果你使用字典的pop()方法并傳入第二個參數(默認), 這個方法會從字典中刪除這個鍵,如果這個鍵不存在則什么都不做。這很有用,因為我們不需要檢查用戶是否已經登入。
@app.route('/logout') def logout():session.pop('logged_in', None)flash('You were logged out')return redirect(url_for('show_entries'))三.模版
layout.html
這個模板包含 HTML 主體結構,標題和一個登錄鏈接(或者當用戶已登入則提供注銷)。如果有閃現信息的話它也將顯示閃現信息。{% block body %} 塊能夠被子模版中的同樣名字(body)的塊替代。
session字典在模版中同樣可用的,你能用它檢查用戶是否登錄。注意在 Jinja 中你可以訪問不存在的對象/字典屬性或成員, 如同下面的代碼, 即便 ‘logged_in’ 鍵不存在,仍然可以正常工作:
<!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>show_entries.html
這個模版繼承了上面的layout.html模版用來顯示信息。注意for遍歷了所有我們用render_template()函數傳入的信息。我們同樣告訴表單提交到add_entry函數通過使用 HTTP 的POST方法:
{% extends "layout.html" %} {% block body %}{% if session.logged_in %}<form action="{{ url_for('add_entry') }}" method=post class=add-entry><dl><dt>Title:<dd><input type=text size=30 name=title><dt>Text:<dd><textarea name=text rows=5 cols=40></textarea><dd><input type=submit value=Share></dl></form>{% endif %}<ul class=entries>{% for entry in entries %}<li><h2>{{ entry.title }}</h2>{{ entry.text|safe }}{% else %}<li><em>Unbelievable. No entries here so far</em>{% endfor %}</ul> {% endblock %}login.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 %}添加樣式
現在其他一切都正常工作,是時候給應用添加些樣式。只要在我們之前創建的static文件夾中新建一個稱為style.css的樣式表:
body { font-family: sans-serif; background: #eee; } a, h1, h2 { color: #377BA8; } h1, h2 { font-family: 'Georgia', serif; margin: 0; } h1 { border-bottom: 2px solid #eee; } h2 { font-size: 1.2em; }.page { margin: 2em auto; width: 35em; border: 5px solid #ccc;padding: 0.8em; background: white; } .entries { list-style: none; margin: 0; padding: 0; } .entries li { margin: 0.8em 1.2em; } .entries li h2 { margin-left: -1em; } .add-entry { font-size: 0.9em; border-bottom: 1px solid #ccc; } .add-entry dl { font-weight: bold; } .metanav { text-align: right; font-size: 0.8em; padding: 0.3em;margin-bottom: 1em; background: #fafafa; } .flash { background: #CEE5F5; padding: 0.5em;border: 1px solid #AACBE2; } .error { background: #F0D6D6; padding: 0.5em; }效果圖
發布時記得將flaskr.py最后一行app.run(debut =True)改為app.run()
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的Flask实战1-轻博客的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python-栈的链式表实现(没写清楚)
- 下一篇: Sublime3 搭建C/C++环境