已经开发了几个flask项目, 是时候总结一下了, 这里涉及到项目源码的组织, 常用的包, 源码示例.
=========================
需要的 python
包有:
=========================
#basic packages
Werkzeug
itsdangerous
Jinja2
Flask
SQLAlchemy
argparse
MarkupSafe, Implements a
XML/HTML/XHTML Markup safe string for Python
#Flask
ext list
Flask-WTF
Flask-SQLAlchemy
Flask-RESTful,
github.com/twilio/flask-restful, 构建restful api, 并以class的形式组织url routing.
Flask-Login,
user登录session方面的管理
Flask-Uploads,
上传文件的插件
flask_principal, 权限插件
Flask-Script, 用来写一些flask app的管理脚本, 需要依赖 argparse 包,
Flask-Bootstrap
Flask-Babel
,本地化和国际化(i18n)
Flask-Cache,
将@cache(timeout=300)放在@route(url)后面, 既可以cache了.
flask-debugtoolbar, http://flask-debugtoolbar.readthedocs.org/en/latest/,
会自动在页面右侧加一个toolbar, 我们可以知道共每个url共花费了多长时间,执行了那些sql
query
=========================
目录结构
=========================
考虑到项目的扩展性, 采用 blueprint 进行组织. 假设 flaskapp 为根目录, 主要的程序放在 app 包中,
除了后台代码, 在app目录下还有templates/static/子目录. 为了重用, 最好的形式是一个建立 boilerplate 项目.
主要参考文档为:
https://github.com/mitsuhiko/flask/wiki/Large-app-how-to
http://www.realpython.com/blog/python/python-web-applications-with-flask-part-ii-app-creation
http://www.realpython.com/blog/python/rethink-flask-a-simple-todo-list-powered-by-flask-and-rethinkdb/
flaskapp
├── app
│ ├── __init__.py
│
├── constants.py
│ ├── users[sub_app/module]
│
│ ├── constants.py
│ │ ├──
decorators.py
│ │ ├── forms.py
│
│ ├── models.py
│ │ └──
views.py
│ ├── tickets[sub_app/module]
│
│ ├── constants.py
│ │ ├──
decorators.py
│ │ ├── forms.py
│
│ ├── models.py
│ │ └──
views.py
│ ├── templates
│ │ ├──
forms
│ │ │ └──
macros.html
│ │ ├── base.html
│ │ ├── index.html
│
│ ├── base_another.html
│ │ ├──
500.html (server error page)
│ │ ├── 404.html (not
found page)
│ │ ├──
method_not_allowed.html
│ │ ├──
access_forbidden.html
│ │ ├── users
│
│ │ ├── profile.html
│
│ │ ├──
login.html
│ │ │ └──
register.html
│ │ └── tickets
│
│ ├──
create.html
│ │ └──
close.html
│ └──
static
│ ├──
favicon.ico
│ ├──
img
│ ├──
js
│ │ ├── main.js #our
own js code
│ │ └──
vendor
│
│ ├── bootstrap.min.js
│
│ └──
jquery-1.7.2.min.js
│ └──
css
│
├──
layout.less
│
├──
reset.less
│
└──
vendor
│
└── bootstrap.css
├── flaskapp.db
├── config.py
├──
requirements.txt
├── runserver.py
├── shell.py
├── tests 目录
└── docs
目录
----------------------
项目级的单元
----------------------
runserver.py 用来启动 web server, 从app包中进入flask
app对象, 然后直接启动.
config.py
存储一些db的 connection 配置, 以及Flask SECRET_KEY 等等. 更多的配置项见
http://flask.pocoo.org/docs/config/
----------------------
应用级别的单元
----------------------
flaskapp/app/__init__.py, 作为整个app的入口, 做如下工作.
1.加载flask的config,
2.[如使用Flask-SQLAlchemy插件]创建 SqlAlchemy 的db 实例.
3.[如没使用Flask-SQLAlchemy插件]定义2个函数, 分别加上@app.before_request和@app.after_request,
也可用@app.teardown_request代替@app.after_request,
为每个request做一些通用的setup和teardown工作, 比如创建和关闭db connection
4.注册sub app blueprint, 比如users和tickets
5.设置root url
和favicon.ico 的路由,
6.创建login_manager,
比如使用flask-login插件来创建一个login_manager
----------------------
子应用级别的单元,
----------------------
称为subapp或称为module,
目录采用
复数形式
flaskapp/app/users/models.py,
和User相关的表模型
flaskapp/app/users/constants.py, 和User module相关的constant,
比如用户的激活状态, 用户的类型.
flaskapp/app/users/forms.py, 集中所有User module相关的表单类,
比如class LoginForm(Form) 和 class RegisterForm(Form)
类.
flaskapp/app/users/decorators.py, 和User module相关的一些decorator, 比如
requires_login, 供 views.py 使用.
flaskapp/app/users/views.py,
充当url路由角色(Flask是基于MVT模型, 这里的view相当于MVC模型中的Controller). 依据web请求类型和请求的url,
路由到指定的view函数, 在view函数中, 做逻辑处理, 然后, 或展现form, 或跳转到其他url.
----------------------
templates目录
----------------------
flaskapp/app/templates/base.html, 模板的模板, 根据需要,
可以设置多个base页面
flaskapp/app/templates/forms/macros.html, 定义一些宏, 供form页面调用,
用来渲染form的元素
flaskapp/app/templates/users/login.html,
在flaskapp/app/users/views.py应该有一个同名的view函数
----------------------
static目录
----------------------
flaskapp/app/static/favicon.ico, 16 ×
16 pixels and in the ICO format
HTTP Method
Action Examples
GET Obtain
information about a resource
http://example.com/api/orders
(retrieve order list)
GET
Obtain information about a resource
http://example.com/api/orders/123
(retrieve order
#123)
POST Create a new resource
http://example.com/api/orders
(create a new order, from data provided
with the request)
PUT Update a resource
http://example.com/api/orders/123
(update order #123, from data
provided with the request)
DELETE Delete a
resource http://example.com/api/orders/123
(delete order
#123)
=========================
源码示例
=========================
------------------------------
runserver.py
------------------------------
runserver.py
用来启动 web server.
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import absolute_import
from app import app
app.run()
------------------------------
config.py
------------------------------
config.py
存储一些db的 connection 配置, 以及Flask SECRET_KEY 等等. 更多的配置项见
http://flask.pocoo.org/docs/config/
# -*- coding: utf-8 -*-
from __future__ import absolute_import
import os
from datetime import timedelta
_basedir = os.path.abspath(os.path.dirname(__file__))
DEBUG = True
SECRET_KEY = os.urandom(24)
PERMANENT_SESSION_LIFETIME=timedelta(seconds=24*60*60)
CSRF_ENABLED = True
CSRF_SESSION_KEY = "somethingimpossibletoguess"
------------------------------
app/__init__.py
------------------------------
flaskapp/app/__init__.py, 作为整个app的入口, 做如下工作.
1.加载flask的config,
2.[如使用Flask-SQLAlchemy插件]创建 SqlAlchemy
的db 实例.
3.[如没使用Flask-SQLAlchemy插件]定义2个函数,
分别加上@app.before_request和@app.after_request,
也可用@app.teardown_request代替@app.after_request,
为每个request做一些通用的setup和teardown工作, 比如创建和关闭db connection
4.注册sub app blueprint, 比如users和tickets
5.设置root url
和favicon.ico 的路由,
6.创建login_manager,
比如使用flask-login插件来创建一个login_manager

# -*- coding: utf-8 -*-
from __future__ import absolute_import
from flask import Flask, g, render_template, send_from_directory
import os
import os.path
_basedir = os.path.abspath(os.path.dirname(__file__))
configPy=os.path.join(os.path.join( _basedir,os.path.pardir), ‘config.py‘)
app = Flask(__name__) # create our application object
app.config.from_pyfile(configPy)
#app.debug=True #change some attribute after load configuration
flask_sqlalchemy_used=True # 如果使用Flask-SQLAlchemy了
db = SQLAlchemy(app) #create a db (SQLAlchemy) object from our app object
login_manager = LoginManager(app) #create a LoginManager Object from our app object
#add our view as the login view to finish configuring the LoginManager
login_manager.login_view = "users.login_view"
#register the users module blueprint
from app.users.views import mod as usersModule
app.register_blueprint(usersModule)
#register the tickets module blueprint
from app.tickets.views import mod as ticketsModule
app.register_blueprint(ticketsModule)
def connect_db(): # 如果没使用Flask-SQLAlchemy
if not flask_sqlalchemy_used:
return sqlite3.connect(‘/path/to/database.db‘)
else:
return None
@app.before_request
def before_request():
"""Make sure we are connected to the database each request."""
if not flask_sqlalchemy_used:
g.db = connect_db()
@app.after_request
def after_request(response):
"""Closes the database again at the end of the request."""
if not flask_sqlalchemy_used:
g.db.close()
return response
#*****************
# controllers
#*****************
@app.route(‘/favicon.ico‘)
def favicon():
return send_from_directory(os.path.join(app.root_path, ‘static‘), ‘ico/favicon.ico‘)
@app.errorhandler(404)
def page_not_found(e):
return render_template(‘404.html‘), 404
@app.route("/")
def index():
return render_template(‘index.html‘)

------------------------------
app/users/views.py.py
------------------------------

# -*- coding: utf-8 -*-
from __future__ import absolute_import
from flask import Blueprint, render_template, flash, redirect, session, url_for, request, g
from flask.ext.login import login_user, logout_user, login_required
from app import app, db, login_manager
from forms import LoginForm, RegistrationForm
from app.users.models import User
mod = Blueprint(‘users‘, __name__) #register the users blueprint module
@login_manager.user_loader
def load_user(user_id):
return User.query.get(user_id)
@mod.route(‘/login/‘, methods=(‘GET‘, ‘POST‘))
def login_view():
form = LoginForm(request.form)
if form.validate_on_submit():
user = form.get_user()
login_user(user)
flash("Logged in successfully.")
return redirect(request.args.get("next") or url_for("index"))
return render_template(‘users/login.html‘, form=form)
@mod.route(‘/register/‘, methods=(‘GET‘, ‘POST‘))
def register_view():
form = RegistrationForm(request.form)
if form.validate_on_submit():
user = User()
form.populate_obj(user)
db.session.add(user) #使用SqlAlchemy保存
db.session.commit()
login_user(user)
return redirect(url_for(‘index‘))
return render_template(‘users/register.html‘, form=form)
@login_required
@mod.route(‘/logout/‘)
def logout_view():
logout_user()
return redirect(url_for(‘index‘))
