現(xiàn)在數(shù)據(jù)庫(kù)連接已經(jīng)正常工作,我們終于可以開(kāi)始寫(xiě)視圖函數(shù)了。我們一共需要寫(xiě) 四個(gè):

顯示條目

這個(gè)視圖顯示數(shù)據(jù)庫(kù)中存儲(chǔ)的所有條目。它綁定在應(yīng)用的根地址,并從數(shù)據(jù)庫(kù)查詢出 文章的標(biāo)題和正文。id 值最大的條目(最新的條目)會(huì)顯示在最上方。從指針?lè)祷氐?行是按 select 語(yǔ)句中聲明的列組織的元組。這對(duì)像我們這樣的小應(yīng)用已經(jīng)足夠了, 但是你可能會(huì)想把它轉(zhuǎn)換成字典。如果你對(duì)這方面有興趣,請(qǐng)參考 簡(jiǎn)化查詢 的例子。

視圖函數(shù)會(huì)將條目作為字典傳遞給 show_entries.html 模板,并返回渲染結(jié)果:

@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)

添加條目

這個(gè)視圖允許已登入的用戶添加新條目,并只響應(yīng) POST 請(qǐng)求,實(shí)際的表單顯示在 show_entries 頁(yè)。如果一切工作正常,我們會(huì)用 flash() 向下 一次請(qǐng)求發(fā)送提示消息,并重定向回 show_entries 頁(yè):

@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 鍵在會(huì)話中存在,并且為 True

安全提示

確保像上面例子中一樣,使用問(wèn)號(hào)標(biāo)記來(lái)構(gòu)建 SQL 語(yǔ)句。否則,當(dāng)你使用格式化 字符串構(gòu)建 SQL 語(yǔ)句時(shí),你的應(yīng)用容易遭受 SQL 注入。 更多請(qǐng)見(jiàn) 在 Flask 中使用 SQLite 3 。

登入和登出

這些函數(shù)用來(lái)讓用戶登入登出。登入通過(guò)與配置文件中的數(shù)據(jù)比較檢查用戶名和密碼, 并設(shè)定會(huì)話中的 logged_in 鍵值。如果用戶成功登入,那么這個(gè)鍵值會(huì)被設(shè)為 True ,并跳轉(zhuǎn)回 show_entries 頁(yè)。此外,會(huì)有消息閃現(xiàn)來(lái)提示用戶登入成功。 如果發(fā)生一個(gè)錯(cuò)誤,模板會(huì)通知,并提示重新登錄。

@app.route('/login', methods=['GET', 'POST'])
def login():
    error = None
    if 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'] = True
            flash('You were logged in')
            return redirect(url_for('show_entries'))
    return render_template('login.html', error=error)

登出函數(shù),做相反的事情,從會(huì)話中刪除 logged_in 鍵。我們這里使用了一個(gè) 簡(jiǎn)潔的方法:如果你使用字典的 pop() 方法并傳入第二個(gè)參數(shù)(默認(rèn)), 這個(gè)方法會(huì)從字典中刪除這個(gè)鍵,如果這個(gè)鍵不存在則什么都不做。這很有用,因?yàn)?我們不需要檢查用戶是否已經(jīng)登入。

@app.route('/logout')
def logout():
    session.pop('logged_in', None)
    flash('You were logged out')
    return redirect(url_for('show_entries'))

繼續(xù) Flask 模板