使用虚拟环境
虚拟环境使用第三方实用工具virtualenv创建。输入一下命令可以检查系统是否安装了virtualenv
virtualenv --version
如果显示错误,你就需要安装这个工具。发行版
大多数Linux发行版都提供了virtualenv包。例如,Ubantu用户可以使用下述命令安装它:
sudo apt-gett install python-virtualenv
如果你的电脑是Mac OS X系统,就可以使用easy_install安装virtualenv:
sudo easy_install virtualenv
如果你使用windows系统或其他没有官方virtualenv包的操作系统,那么安装程序要稍微复杂一点。
windows安装virtuaalenv
1.windows下载虚拟环境virtualenv
https://bitbucket.org/pypa/setuptools
2.找到ez_setup.py并点击下载
3.在这个文件夹中以管理员身份执行以下命令:
python ez_setup.py easy_install virtualenv
创建虚拟环境并激活
首先进入目标文件夹,然后执行virtualenv venv 创建虚拟环境
激活:venvScriptsactivate
linu和Mac OS X :source venv/bin/activate
回到全局Python解释器:deactivate
安装flask
进入虚拟环境然后安装flask:pip install flask
完整的程序
from flask import Flask app = Flask(__name__) @app.route('/') def index(): return 'hello.world' if __name__ == '__main__': app.run(debug=True)
flask-script支持命令行选项
安装:pip install flask-script
使用:
from flask.ext.script import Manager app = Flask(__name__) manager = Manager(app)
使用janja2模板渲染
templates/user.html
{% if name %} <h1>hello,{{ name }}</h1> {% else %} <h1>hello,world</h1> {% endif %}
hello.py
@app.route('/') def index(): return render_template('user.html') @app.route('/user/<name>') def user(name): return render_template('user.html',name=name)
使用Bootstrap集成Twitter Bootstrap
安装:pip install flask-bootstrap
导入:
from flask.ext.bootstrap import Bootstrap app = Flask(__name__) bootstrap = Bootstrap(app)
templates/user.html 使用bootstrap模板:
bootstrap中文网
使用 BootCDN 提供的免费 CDN 加速服务(同时支持 http 和 https 协议)
<!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <!-- 可选的 Bootstrap 主题文件(一般不用引入) --> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"> <!-- 最新的 Bootstrap 核心 JavaScript 文件 --> <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
使用Flask-Moment本地化日期和时间
安装:pip install flask-moment
初始化:
from flask_moment import Moment moment = Moment(app)
html中引入moment.js
{% block script %} {{ super() }} {{ moment.include_moment() }} {% endblock %}
hello.py加入一个datatime变量
from flask_moment import Moment from datetime import datetime moment = Moment(app) @app.route('/') def index(): return render_template('index.html',current_time = datetime.utcnow())
模板中渲染current_time
<p>现在的时间是{{ moment(current_time).format('LLL') }}</p> <p>That was {{ moment(current_time).fromNow(refresh=True) }}</p>
使用表单
安装:pip install flask_wtf
为了保护所有表单免受跨站请求伪造,需要设置一个密钥。和设置字典一样直接赋值
from flask_wtf import Form from wtforms import StringField,SubmitField from wtforms.validators import Required app.config['SECRET_KEY'] = 'hard to guess string'
创建表单
class NameForm(Form): name = StringField(u'你的名字') submit = SubmitField(u'提交')
在视图函数中引入表单
@app.route('/',methods=['GET','POST']) def index(): form = NameForm() if form.validate_on_submit(): session['name'] = form.name.data return redirect(url_for('index')) return render_template('index.html',form=form ,name=session.get('name'))
在HTML中渲染表单
{% import 'bootstrap/wtf.html' as wtf %} <form method="post"> {{ wtf.quick_form(form) }} </form>
flash消息
导入:from flask import flash
使用:
flash(‘’......‘’)
在html中渲染:
{% for message in get_flashed_messages() %} <div class="alert alert-warning"> <button type="button" class="close" data-dismiss="alert">×</button> {{ message }} </div> {% endfor %}
使用Flask-SQLAlchemy管理数据库
使用python连接mysql
首先安装mysql-python
linux:pip install mysql-python
windows:链接:www.lfd.uci.edu/~gohlke/pythonlibs/#mysql-python
点击MySQL_python-1.2.5-cp27-NONE-win32.whl下载
pip install MySQL_python-1.2.5-cp27-NONE-win32.whl安装
安装:pip install flask-sqlalchemy
导入
from flask_sqlalchemy import SQLAlchemy import os basedir = os.path.abspath(os.path.dirname(__file__)) app.config.from_object('config')
db = SQLAlchemy(app)
db.create_all()
在flask-sqlalchemy中,数据库使用URL指定。最流行的数据库引擎采用的数据库URL格式如下
数据库引擎 URL
Mysql mysql://username:password@hostname/database Postgres postgresql://username:password@hostname/database SQLite(Unix) sqlite:////absolute/path/to/database SQLITE(windows) sqlite:///c:/absolute/path/to/database
配置数据库:dialect+driver://username:password@host:port/databases
config.py
DIALECT = 'mysql' DRIVER = 'mysqldb' USERNAME = 'root' PASSWORD = ' ' HOST = '127.0.0.1' PORT = '3306' DATABASES = 'dbdemo' SQLALCHEMY_DATABASE_URI= '{}+{}://{}:{}@{}:{}/{}?charset=utf8'.format(DIALECT,DRIVER,USERNAME,PASSWORD,HOST,PORT,DATABASES) SQLALCHEMY_COMMIT_ON_TEARDOWN=True SQLALCHEMY_TRACK_MODIFICATIONS=False
创建表
class Role(db.Model): __tablename__ = 'roles' id = db.Column(db.Integer,primary_key=True) name = db.Column(db.String(64),unique=True) users = db.relationship('User', backref='role') def __repr__(self): return '<Role %r>'%self.name class User(db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(64), unique=True ,index=True) role_id = db.Column(db.Integer,db.ForeignKey('role.id')) def __repr__(self): return '<User %r>' % self.username
使用工厂函数:
app/__init__.py: from flask import Flask,render_template,url_for,redirect,session,flash from flask_bootstrap import Bootstrap from flask_moment import Moment from flask_sqlalchemy import SQLAlchemy from config import config bootstrap = Bootstrap() moment = Moment() db = SQLAlchemy() def create_app(config_name): app = Flask(__name__) app.config.from_object(config[config_name]) config[config_name].init_app(app) bootstrap.init_app(app) moment.init_app(app) db.init_app(app) return app
在蓝本中实现程序功能:
app/main/__init__.py:
from flask import Blueprint Blueprint('main',__name__) from . import views,errors
app/__init__.py注册蓝本
def create_app(config_name) from .main import main as main_bluprent app.register_blueprint(main_bluprent) return app
使用Werkzeug实现密码散列
app/models.py 在User模型中加入密码散列
class User(db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(64), unique=True,index=True) role_id = db.Column(db.Integer,db.ForeignKey('roles.id')) password_hash = db.Column(db.String(128)) @property def password(self): raise AttributeError('password is not a readable attribute') @password.setter def password(self,password): self.password_hash = generate_password_hash(password) def verify_password(self,password): return check_password_hash(self.password_hash,password)
User表的静态方法:password错误会触发AttributeError
password_hash就是generate_password_hash生成的hash值
verify_password需要传入password,和password_hash比较,如果正确则返回True
在shell中测试:
(venv) python manage.py shell
>>> u = User() >>> u.password = 'cat' >>> u.password_hash 'pbkdf2:sha256:50000$wBooo1Ro$b3e3d42ce34ca1e886726cc94ccecf0b274c3de913876d508837d63aabd44b1c' >>> u.verify_password('cat') True >>> u.verify_password('dog') False >>> u2 = User() >>> u2.password = 'cat' >>> u2.password_hash 'pbkdf2:sha256:50000$5mLqP9WH$8f4d60676d30eb2d4c3f4b9c16e19b468998b5fd4dea6cf48611469da432f8e2'
密码散列化测试:
tests/test_user_models.py
import unittest from app.models import User class UserModelTestCase(unittest.TestCase): def test_password_setter(self): u = User(password = 'cat') self.assertTrue(u.password_hash is not None) def test_no_password(self): u = User(password = 'cat') with self.assertRaises(AttributeError): u.password def test_password_verfication(self): u = User(password = 'cat') self.assertTrue(u.verify_password('cat')) self.assertFalse(u.verify_password('dog')) def test_password_salts_are_random(self): u = User(password='cat') u2 = User(password='cat') self.assertTrue(u.password_hash != u2.password_has
创建认证蓝本
app/auth/__init__.py
from flask import Blueprint auth = Blueprint('auth',__name__) from . import views
在app/__init__中注册
from .auth import auth as auth_blueprint app.register_blueprint(auth_blueprint,url_prefix='/auth')
app/auth/views.py
from flask import render_template from . import auth @auth.route('/login') def login(): return render_template('auth/login.html')
使用Flask-login认证用户
*安装:pip install flask-login
准备用于登录的用户模型
Flask-Login要求实现的用户方法
*方法 说明
is_authenticated 如果用户已经登录,必须返回True,否则返回False
is_active 如果允许用户登录,必须返回True,否则返回False。如果要禁用用户,可以返回False
is_anonymous 对普通用户必须返回False
get_id 必须返回用户的唯一标识符,使用unicode编码字符串
*flask—login提供了一个UserMixin类,其中包含这些方法的默认实现,需要在数据库中继承
*初始化:
app/__init__.py:
from flask_login import LoginManager login_manager = LoginManager() login_manager.session_protection='strong' login_manager.login_view = 'auth.login'
login_manager.session_protection属性可以设为None,‘basic’或‘strong’,以提供不同的安全等级防止用户会话遭篡改
设为strong时,会记录客户端IP地址和浏览器的用户代理信息,如果发现异动就登出用户。
login_view属性设置登录页面的端点
*最后,Flask_login要求程序实现一个回调函数,使用指定的标识符加载用户。
app/models.py
from . import login_manager @login_manager.user_loader() def load_user(user_id): return User.query.get(int(user_id))
加载用户的回调函数接收Unicode字符串形式表示的用户标识符。如果能找到用户,这个函数必须返回用户对象;否则应该返回None
*保护路由
为了保护路由只让认证用户访问,Flask-login提供了一个login_required修饰器,未认证的用户访问这个路由,会拦截请求把用户发往登录页面
from flask_login import login_required @app.route('/secret') @login_required def secret(): return 'Only authenticated users are allowed'
打开URL
manage.py
@manager.command def dev(): from livereload import Server live_server = Server(app.wsgi_app) live_server.watch('**/*.*') live_server.serve(open_url = True)