flask 范例学习

链接在此:http://dormousehole.readthedocs.org/en/latest/tutorial/introduction.html

  当然,直接根据上述链接一步一步来就可以实现所有的功能。但是,根据我在学习的过程中的心得,我觉得有必要记录一下。

  一。环境搭建

    跟前面我的记录的flask环境搭建有些不同,我在这里介绍另外一种搭建环境的方式。

    首先,从github上面下载flask。可以直接下载tar文件,或者在安装来git环境的情况下直接键入如下命令:

git clone https://github.com/mitsuhiko/flask.git

    其次,由于flask会依赖于两个外部库,我们也如上从github上面下载:

git clone https://github.com/mitsuhiko/jinja2.git

git clone https://github.com/mitsuhiko/werkzeug.git

二。目标

  我们将要创建一个博客应用。1.可以登录和注销。2.可以添加博客条目。3.页面以一定的顺序来显示。

三。创建应用所需文件夹

/flaskr
    /static
    /templates
    /tmp

  其中flaskr是我们应用的主文件夹,static文件夹用于存放css和js等布局文件,templates里面存放html文件,tmp文件夹存放后续生成的数据库文件。

 四。生成数据库表单

  由于我们使用的是sql数据库,所以新建一个schema.sql文件用于存放博客数据库表结构。

drop table if exists entries;
create table entries(
    id integer primary key autoincrement,
    title string not null,
    text string not null
)

  对于sql的数据库语法虽然不是很明了,但是上述语句很容易理解。注意:上面的最后一句text后不能想当然的添加一个逗号“,”。

五。创建应用服务器的主体

  创建flaskr.py文件,键入如下命令:

from flask import Flask, request, session, g, redirect, url_for, \
    abort, render_template, flash

#for detail


app = Flask( __name__ )

if __name__ == "__main__":
     app.run()

此时可以在终端输入 python flaskr.py来启动服务器,然后在127.0.0.1:5000页面查看结果。由于没有视图渲染,所以会看到404 not found。

六。创建数据库

  由于我们要将博客名称和内容存储进数据库,所以,我们先生成必要的数据库表单。

  首先,我们需要将本地的sqlite3和我们所创建的数据库结构连接起来:

#import database
import sqlite3

#define configure data
DATABASE = 'tmp/flaskr.db'

#connect global var to app
app.config.from_object(__name__)

def connect_db():
    return sqlite3.connect( app.config['DATABASE'] )

  其次,这部分不是很理解,暂时不解释:

from __future__ import with_statement
from contextlib import closing

def init_db():
    with closing( connect_db() ) as db:
        with app.open_resource( 'schema.sql' ) as f:
            db.cursor().executescript( f.read() )
        db.commit()

 上述完成之后,可以在python的shell环境中生成数据库表。

>>> from flaskr import init_db
>>> init_db()

如果没有出现错误提示,就说明表已经被创建好了。

 七。请求数据库连接

  后续我们所发起的http请求,均与数据库有关,所以需要在请求到达的时候,和数据库进行关联。这就要靠before_request和teardown_request装饰器。

@app.before_request
def before_request():
    g.db = connect_db()

@app.teardown_request
def teardown_request(exception):
    g.db.close()

  这里面要注意的是g变量,这是flask的一个全局对象,它只在一个请求中起作用。所以将db保存到g中很方便。

八。视图函数

  这回我们将要接近主题了,这个视图函数在MVC模型里面来说其实就是控制器C(controller)。我们首先看一下主页面的显示:

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

  @app.route装饰器作用是将请求路由到对应的函数,即“127.0.0.1:5000/”就对应的show_entries函数。由于刚才我们保存了与数据库的连接到g.db,所以这次我们直接使用来查询数据库。entries是根据表的内容,生成一个包含title和text对的数组。

  接下来我们直接添加视图,先来体验以下效果,在templates文件下添加layout.html文件和show_entries.html文件。layout.html是一个模板,通用的。

<!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>

  注意:这里面使用的url_for可以查找到static目录下的style.css文件,如果style.css在css目录下,则static应更换为static.css。

{% 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 %}

   进行到这里,可以在127.0.0.1:5000页面查看效果了,但是你会发现,提示“login”等方法错误。那是因为我们还没有添加“login”方法进来。可以先预留出空间,保证我们目前的例子可以通过。添加如下代码:

@app.route('/login', methods=['GET', 'POST'])
def login():
    pass

@app.route('/logout')
def logout():
    pass

 ok,只要细心,到这一步,我门就算初步成功。页面没有布局(css文件未导入),而且只有login的标签(login目前还不能使用)。

  九。完善视图

  接下来我们完善视图。添加login和add视图控制函数,此时还需要添加全局变量,例如登陆密码等。

SECRET_KEY = 'development key'
USERNAME = 'admin'
PASSWORD = 'default'
@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)
@app.route('/logout')
def logout():
    session.pop('logged_in', None)
    flash('You were logged out')
    return redirect(url_for('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'))

十。完善视图

{% 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 %}

十一。添加样式表单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; }

ok,大功告成。 

原文地址:https://www.cnblogs.com/bracken/p/2882123.html