前言:
Django:1個重武器,包含了web開發中經常使用的功能、組件的框架;(ORM、Session、Form、Admin、分頁、中間件、信號、緩存、ContenType....);css
Tornado:2大特性就是異步非阻塞、原生支持WebSocket協議;html
Flask:功能和性能雖然不及Django和Tornado,可是Flask的第三方開源組件比豐富;http://flask.pocoo.org/extensions/python
Bottle:比較簡單;web
總結:正則表達式
都不是我寫的!!!不論優劣,不一樣的工具而已;redis
小型web應用設計的功能點很少使用Flask;sql
大型web應用設計的功能點比較多使用的組件也會比較多,使用Django(自帶功能多不用去找插件);mongodb
若是追求性能能夠考慮Tornado;json
Flask的socket是基於Werkzeug 實現的,模板語言依賴jinja2模板,在使用Flask以前須要安裝一下;flask
pip3 install flask #安裝flask

from werkzeug.wrappers import Request, Response # Flask的socket使用werkzeug實現,因此要導入 werkzeug @Request.application def hellow(request): return Response('Hello World') if __name__ == '__main__': from werkzeug.serving import run_simple run_simple('localhost',400,hellow)
Flask簡單使用

from flask import Flask app=Flask(__name__) #建立1個Flask實例 @app.route('/') #路由系統生成 視圖對應url,1. decorator=app.route() 2. decorator(first_flask) def first_flask(): #視圖函數 return 'Hello World' #response if __name__ == '__main__': app.run() #啓動socket
1、配置文件
app=Flask(__name__,template_folder='templates',static_url_path='/static/',static_path='/zhanggen')
模板路徑: template_folder='templates'
靜態文件路徑:static_url_path='/static/'
靜態文件引入別名:static_path='/zhanggen'
設置爲調試環境:app.debug=True (代碼修改自動更新)
設置json編碼格式 若是爲False 就不使用ascii編碼:app.config['JSON_AS_ASCII']=False
設置響應頭信息Content-Type app.config['JSONIFY_MIMETYPE'] ="application/json;charset=utf-8" (注意 ;charset=utf-8)
2、路由系統
1.動態路由(url傳參)
@app.route('/user/<name>')

from flask import Flask app=Flask(__name__) @app.route('/<name>') #設置url傳參數 http://127.0.0.1:5000/zhanggen def first_flask(name): #視圖必須有對應接收參數 print(name) return 'Hello World' #response if __name__ == '__main__': app.run()
@app.route('/post/<int:age>')

#接收整型數字參數 app=Flask(__name__) @app.route('/<int:age>/') #設置url傳參數 http://127.0.0.1:5000/18/ def first_flask(age): #視圖必須有對應接收參數 print(age) return 'Hello World' #response if __name__ == '__main__': app.run()
@app.route('/post/<float:salary>')

#接收浮點型型數字參數 app=Flask(__name__) @app.route('/<float:salary>/') #設置url傳參數http://127.0.0.1:5000/2345555.8889/ def first_flask(salary): #視圖必須有對應接收參數 print(salary) return 'Hello World' #response if __name__ == '__main__': app.run()
@app.route('/post/<path:path>')

# 接收URL連接類型參數 app=Flask(__name__) @app.route('/<path:url>/') #設置url傳參數:http://127.0.0.1:5000/http://www.baiu.com/ def first_flask(url): #視圖必須有對應接收參數 print(url) return 'Hello World' #response if __name__ == '__main__': app.run()
二、指定容許的請求方法
@app.route('/login', methods=['GET', 'POST'])

# 指定容許的請求方法 app=Flask(__name__) @app.route('/<path:url>/',methods=['get']) #只容許get請求 def first_flask(url): print(url) return 'Hello World' #response if __name__ == '__main__': app.run()
三、經過別名反向生成url

#反向生成url from flask import Flask,url_for app=Flask(__name__) @app.route('/<path:url>',endpoint='name1') def first_flask(url): print(url_for('name1',url=url)) #若是設置了url參數,url_for(別名,加參數) return 'Hello World' if __name__ == '__main__': app.run()
四、經過app.add_url_rule()調用路由

#方式2經過app.add_url_rule()方法的方式調用路由 app=Flask(__name__) def first_flask(): return 'Hello World' app.add_url_rule(rule='/index/',endpoint='name1',view_func=first_flask,methods=['GET']) #app.add_url_rule(rule=訪問的url,endpoint=路由別名,view_func=視圖名稱,methods=[容許訪問的方法]) if __name__ == '__main__': app.run()
五、擴展路由功能:正則匹配url
若是須要一些複雜的匹配規則能夠自定義正則匹配url

from flask import Flask, views, url_for from werkzeug.routing import BaseConverter app = Flask(import_name=__name__) class RegexConverter(BaseConverter): """ 自定義URL匹配正則表達式 """ def __init__(self, map, regex): super(RegexConverter, self).__init__(map) self.regex = regex def to_python(self, value): """ 路由匹配時,匹配成功後傳遞給視圖函數中參數的值 :param value: :return: """ return int(value) def to_url(self, value): """ 使用url_for反向生成URL時,傳遞的參數通過該方法處理,返回的值用於生成URL中的參數 :param value: :return: """ val = super(RegexConverter, self).to_url(value) return val # 添加到flask中 app.url_map.converters['regex'] = RegexConverter @app.route('/index/<regex("\d+"):nid>') def index(nid): print(url_for('index', nid='888')) return 'Index' if __name__ == '__main__': app.run()
4、視圖
一、給Flask視圖函數加裝飾器
注意若是要給視圖函數加裝飾器增長新功能,一點要加在路由裝飾器下面,纔會被路由裝飾器裝飾,才能生生成url關係;

#給Flask視圖加裝飾器 #一、定義1個裝飾器 def auth(func): print('我在上面') def inner(*args,**kwargs): return func(*args,**kwargs) return inner app=Flask(__name__) @app.route('/',methods=['GET']) @auth #注意若是要給視圖函數加裝飾器,一點要加在路由裝飾器下面,纔會被路由裝飾器裝飾 def first_flask(): print('ffff') return 'Hello World' if __name__ == '__main__': app.run()
二、request和response
a.請求相關信息
request.method: 獲取請求方法
request.json
request.json.get("json_key"):獲取json數據 **較經常使用
request.argsget('name') :獲取get請求參數
request.form.get('name') :獲取POST請求參數
request.form.getlist('name_list'):獲取POST請求參數列表(多個)
request.values.get('age') :獲取GET和POST請求攜帶的全部參數(GET/POST通用)
request.cookies.get('name'):獲取cookies信息
request.headers.get('Host'):獲取請求頭相關信息
request.path:獲取用戶訪問的url地址,例如(/,/login/,/ index/);
request.full_path:獲取用戶訪問的完整url地址+參數 例如(/login/?age=18)
request.script_root: 抱歉,暫未理解其含義;
request.url:獲取訪問url地址,例如http://127.0.0.1:5000/?age=18;
request.base_url:獲取訪問url地址,例如 http://127.0.0.1:5000/;
request.url_root
request.host_url
request.host:獲取主機地址
request.files:獲取用戶上傳的文件
obj = request.files['the_file_name']
obj.save('/var/www/uploads/' + secure_filename(f.filename)) 直接保存
b、響應相關信息
return "字符串" :響應字符串
return render_template('html模板路徑',**{}):響應模板
return redirect('/index.html'):跳轉頁面
響應json數據
方式1: return jsonify(user_list)

app.config['JSON_AS_ASCII']=False #指定json編碼格式 若是爲False 就不使用ascii編碼, app.config['JSONIFY_MIMETYPE'] ="application/json;charset=utf-8" #指定瀏覽器渲染的文件類型,和解碼格式;
方式2:
return Response(data,mimetype="application/json;charset=utf-8",)
若是須要設置響應頭就須要藉助make_response()方法
from flask import Flask,request,make_response
response = make_response(render_template('index.html'))
response是flask.wrappers.Response類型
response.delete_cookie('key')
response.set_cookie('key', 'value')
response.headers['X-Something'] = 'A value'
return respons
3 、Flask之CBV視圖

#CBV視圖 from flask import Flask,url_for,views #----------------------------------------------------- app=Flask(__name__) #裝飾器 def auth(func): print('我在上面') def inner(*args,**kwargs): return func(*args,**kwargs) return inner #-------------------------------------------------------- class IndexView(views.MethodView): #CBV視圖 methods=['GET'] #容許的http請求方法(改CBV只容許GET方法) decorators = [auth,] #每次請求過來都加auth裝飾器 def get(self): return 'Index.GET' def post(self): return 'Index.POST' app.add_url_rule('/index/',view_func=IndexView.as_view(name='name1')) #(name='name1'反向生成url別名 if __name__ == '__main__': app.run()
5、模板語言
Flask使用的是Jinja2模板,因此其語法和Django無差異(Django的模板語言參考Jinja2)
1.引用靜態文件
方式1:別名引入
<link rel="stylesheet" href="/zhanggen/commons.css">
方式2:url_for()方法引入
<link rel="stylesheet" href="{{ url_for('static',filename='commons.css') }}">
2.模板語言引用上下文對象
變量

<h1>{{user_list}}</h1> <!--變量 -->
循環、索引取值

<ul> {% for user in user_list %} <!--循環 --> <li>{{user}}</li> {% endfor %} {{user_list.0}} <!-- 索引取值--> </ul>
Flask的Jinjia2能夠經過Context 把視圖中的函數傳遞把模板語言中執行,這就是Django中的simple_tag和simple_fifter;
simple_tag(只能傳2個參數,支持for、if)

@app.template_global() #simple_tag def foo(arg): return '<input type="text">'

<h1>{{foo(1)|safe}}</h1> <!--Flask的模板語言支持simple_tag-->
simple_fifter(對參數個數無限制,不支持for、if)

@app.template_filter() #simple_fifter def foo1(arg1,arg2,arg3): return arg1+arg2+arg3

<h1> {{ 'alex'|foo1('s ','b',) }} </h1> <!-- simple_fifter -->
6、session功能
1. Flask自帶的session功能

from flask import session import json app=Flask(__name__,template_folder='templates',static_path='/static/',static_url_path='/static/') app.debug=True app.secret_key='sjehfjeefrjewth43u' #設置session加密 app.config['JSON_AS_ASCII']=False #指定json編碼格式 若是爲False 就不使用ascii編碼, app.config['JSONIFY_MIMETYPE'] ="application/json;charset=utf-8" #指定瀏覽器渲染的文件類型,和解碼格式; @app.route('/login/',methods=['GET','POST']) def login(): msg = '' if request.method=='POST': name=request.values.get('user') pwd=request.values.get('pwd') if name =='zhanggen' and pwd=='123.com': session['user']=name #設置session的key value return redirect('/index/') else: msg='用戶名或者密碼錯誤' return render_template('login.html',msg=msg) @app.route('/index/',methods=['GET','POST']) def index(): user_list = ['張根', 'egon', 'eric'] user=session.get('user') #獲取session if user: user=['alex','egon','eric'] return jsonify(user_list) else: return redirect('/login/') if __name__ == '__main__': app.run()
2.第三方session組件(Session)
安裝 pip install flask-session

from flask import session, Flask,request,make_response,render_template,redirect,jsonify,Response from flask.ext.session import Session #引入第三方session import json app=Flask(__name__,template_folder='templates',static_path='/static/',static_url_path='/static/') app.debug=True app.secret_key='sjehfjeefrjewth43u' #設置session加密 app.config['JSON_AS_ASCII']=False #指定json編碼格式 若是爲False 就不使用ascii編碼, app.config['JSONIFY_MIMETYPE'] ="application/json;charset=utf-8" #指定瀏覽器渲染的文件類型,和解碼格式; app.config['SESSION_TYPE']='redis' from redis import Redis #引入鏈接 redis模塊 app.config['SESSION_REDIS']=Redis(host='192.168.0.94',port=6379) #鏈接redis Session(app) @app.route('/login/',methods=['GET','POST']) def login(): msg = '' if request.method=='POST': name=request.values.get('user') pwd=request.values.get('pwd') if name =='zhanggen' and pwd=='123.com': session['user']=name #設置session的key value return redirect('/index/') else: msg='用戶名或者密碼錯誤' return render_template('login.html',msg=msg) @app.route('/index/',methods=['GET','POST']) def index(): user_list = ['張根', 'egon', 'eric'] user=session.get('user') #獲取session if user: user=['alex','egon','eric'] return jsonify(user_list) else: return redirect('/login/') if __name__ == '__main__': app.run()
不只能夠把session存放到redis還可放到文件、內存、memcache...

def _get_interface(self, app): config = app.config.copy() config.setdefault('SESSION_TYPE', 'null') config.setdefault('SESSION_PERMANENT', True) config.setdefault('SESSION_USE_SIGNER', False) config.setdefault('SESSION_KEY_PREFIX', 'session:') config.setdefault('SESSION_REDIS', None) config.setdefault('SESSION_MEMCACHED', None) config.setdefault('SESSION_FILE_DIR', os.path.join(os.getcwd(), 'flask_session')) config.setdefault('SESSION_FILE_THRESHOLD', 500) config.setdefault('SESSION_FILE_MODE', 384) config.setdefault('SESSION_MONGODB', None) config.setdefault('SESSION_MONGODB_DB', 'flask_session') config.setdefault('SESSION_MONGODB_COLLECT', 'sessions') config.setdefault('SESSION_SQLALCHEMY', None) config.setdefault('SESSION_SQLALCHEMY_TABLE', 'sessions') if config['SESSION_TYPE'] == 'redis': session_interface = RedisSessionInterface( config['SESSION_REDIS'], config['SESSION_KEY_PREFIX'], config['SESSION_USE_SIGNER'], config['SESSION_PERMANENT']) elif config['SESSION_TYPE'] == 'memcached': session_interface = MemcachedSessionInterface( config['SESSION_MEMCACHED'], config['SESSION_KEY_PREFIX'], config['SESSION_USE_SIGNER'], config['SESSION_PERMANENT']) elif config['SESSION_TYPE'] == 'filesystem': session_interface = FileSystemSessionInterface( config['SESSION_FILE_DIR'], config['SESSION_FILE_THRESHOLD'], config['SESSION_FILE_MODE'], config['SESSION_KEY_PREFIX'], config['SESSION_USE_SIGNER'], config['SESSION_PERMANENT']) elif config['SESSION_TYPE'] == 'mongodb': session_interface = MongoDBSessionInterface( config['SESSION_MONGODB'], config['SESSION_MONGODB_DB'], config['SESSION_MONGODB_COLLECT'], config['SESSION_KEY_PREFIX'], config['SESSION_USE_SIGNER'], config['SESSION_PERMANENT']) elif config['SESSION_TYPE'] == 'sqlalchemy': session_interface = SqlAlchemySessionInterface( app, config['SESSION_SQLALCHEMY'], config['SESSION_SQLALCHEMY_TABLE'], config['SESSION_KEY_PREFIX'], config['SESSION_USE_SIGNER'], config['SESSION_PERMANENT']) else: session_interface = NullSessionInterface() return session_interface
3.自定義session組件

#!/usr/bin/env python # -*- coding:utf-8 -*- import uuid import json from flask.sessions import SessionInterface from flask.sessions import SessionMixin from itsdangerous import Signer, BadSignature, want_bytes class MySession(dict, SessionMixin): def __init__(self, initial=None, sid=None): self.sid = sid self.initial = initial super(MySession, self).__init__(initial or ()) def __setitem__(self, key, value): super(MySession, self).__setitem__(key, value) def __getitem__(self, item): return super(MySession, self).__getitem__(item) def __delitem__(self, key): super(MySession, self).__delitem__(key) class MySessionInterface(SessionInterface): session_class = MySession container = {} def __init__(self): import redis self.redis = redis.Redis() def _generate_sid(self): return str(uuid.uuid4()) def _get_signer(self, app): if not app.secret_key: return None return Signer(app.secret_key, salt='flask-session', key_derivation='hmac') def open_session(self, app, request): """ 程序剛啓動時執行,須要返回一個session對象 """ sid = request.cookies.get(app.session_cookie_name) if not sid: sid = self._generate_sid() return self.session_class(sid=sid) signer = self._get_signer(app) try: sid_as_bytes = signer.unsign(sid) sid = sid_as_bytes.decode() except BadSignature: sid = self._generate_sid() return self.session_class(sid=sid) # session保存在redis中 # val = self.redis.get(sid) # session保存在內存中 val = self.container.get(sid) if val is not None: try: data = json.loads(val) return self.session_class(data, sid=sid) except: return self.session_class(sid=sid) return self.session_class(sid=sid) def save_session(self, app, session, response): """ 程序結束前執行,能夠保存session中全部的值 如: 保存到resit 寫入到用戶cookie """ domain = self.get_cookie_domain(app) path = self.get_cookie_path(app) httponly = self.get_cookie_httponly(app) secure = self.get_cookie_secure(app) expires = self.get_expiration_time(app, session) val = json.dumps(dict(session)) # session保存在redis中 # self.redis.setex(name=session.sid, value=val, time=app.permanent_session_lifetime) # session保存在內存中 self.container.setdefault(session.sid, val) session_id = self._get_signer(app).sign(want_bytes(session.sid)) response.set_cookie(app.session_cookie_name, session_id, expires=expires, httponly=httponly, domain=domain, path=path, secure=secure)

from flask import Flask from flask import session from my_session import MySessionInterface app = Flask(__name__) app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT' app.session_interface = MySessionInterface() @app.route('/login/', methods=['GET', "POST"]) def login(): print(session) session['user1'] = 'alex' session['user2'] = 'alex' del session['user2'] return "內容" if __name__ == '__main__': app.run()
7、藍圖
使用Flask自帶Blueprintmuk模塊,幫助咱們作代碼目錄結構的歸類

import luffy #導入luffy包就會執行luffy包中__init__.py文件 luffy.app.run()

from flask import Flask app=Flask(__name__,template_folder='templates',static_path='/static/',static_url_path='/static/') app.debug=True from .views import login from .views import index #把文件中藍圖對象註冊到app裏 app.register_blueprint(login.login,url_prefix='/login') #訪問login藍圖必須以url_prefix開頭 app.register_blueprint(index.index,url_prefix='/index') if __name__ == '__main__': app.run()

from flask import Blueprint #導入藍圖 login=Blueprint('login',__name__) #在本模塊實例化1個藍圖 @login.route('/login/',methods=['GET','POST']) def login1(): return '登陸頁面'

from flask import Blueprint index=Blueprint('index',__name__) @index.route('/index/',methods=['GET','POST']) def index1(): return '首頁'
8、message (閃現)
message是一個基於Session實現的用於保存數據的集合,其特色是:一次性。
特色:和labada匿名函數同樣不長期佔用內存

from flask import Flask,request,flash,get_flashed_messages app = Flask(__name__) app.secret_key = 'some_secret' @app.route('/set/') def index2(): flash('Disposable') #在message中設置1個個值 return 'ok' #--------------------------------------------------------------------------------- @app.route('/') def index1(): messages = get_flashed_messages() #獲取message中設置的值,只能獲取1次。(1次性) print(messages) return "Index1" if __name__ == "__main__": app.run()
9、中間件
flask也有中間件功能和Django相似,不一樣的是使用的是使用3個裝飾器來實現的;
1.@app.before_first_request :請求第1次到來執行1次,以後都不執行;
2.@app.before_request:請求到達視圖以前執行;(改函數不能有返回值,不然直接在當前返回)
3.@app.after_request:請求 通過視圖以後執行;(最下面的先執行)

#!/usr/bin/env python # -*- coding:utf-8 -*- from flask import Flask, Request, render_template app = Flask(__name__, template_folder='templates') app.debug = True @app.before_first_request #第1個請求到來執行 def before_first_request1(): print('before_first_request1') @app.before_request #中間件2 def before_request1(): Request.nnn = 123 print('before_request1') #不能有返回值,一旦有返回值在當前返回 @app.before_request def before_request2(): print('before_request2') @app.errorhandler(404) def page_not_found(error): return 'This page does not exist', 404 @app.route('/') def hello_world(): return "Hello World" @app.after_request #中間件 執行視圖以後 def after_request1(response): print('after_request1', response) return response @app.after_request #中間件 執行視圖以後 先執行 after_request2 def after_request2(response): print('after_request2', response) return response if __name__ == '__main__': app.run()
10、Flask插件
WTForms
SQLAchemy
等... 詳細見:http://flask.pocoo.org/extensions/
文檔:http://docs.jinkan.org/docs/flask/quickstart.html
銀角大王:http://www.cnblogs.com/wupeiqi/articles/7552008.html
銀角大王:http://www.cnblogs.com/wupeiqi/articles/5713330.html(執行原生SQL模塊 pymsql ,ORM框架 SQLAchemy)