Django:1個重武器,包含了web開發中經常使用的功能、組件的框架;(ORM、Session、Form、Admin、分頁、中間件、信號、緩存、ContenType....);css
Tornado:2大特性就是異步非阻塞、原生支持WebSocket協議;html
Flask:封裝功能不及Django完善,性能不及Tornado,可是Flask的第三方開源組件比豐富;http://flask.pocoo.org/extensions/前端
Bottle:比較簡單;html5
總結:python
都不是我寫的!!!不論優劣,不一樣的工具而已;web
小型web應用設計的功能點很少使用Flask;正則表達式
大型web應用設計的功能點比較多使用的組件也會比較多,使用Django(自帶功能多不用去找插件);redis
若是追求性能能夠考慮Tornado;sql
Flask的socket是基於Werkzeug 實現的,模板語言依賴jinja2模板,在使用Flask以前須要安裝一下;mongodb
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)
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
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)
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()
一、給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()
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 -->
3.wtform(flask表單驗證插件)
3.0.簡介
wtforms WTForms是一個支持多個web框架的form組件,主要對用戶請求數據 進行表單驗證。
3.1. 安裝
pip install wtforms #安裝wtfroms插件
3.2.簡單使用
wtforms和Django自帶的form驗證插件功能相同,使用起來大同小異;
用戶登陸頁面驗證
#!/usr/bin/env python # -*- coding:utf-8 -*- from flask import Flask, render_template, request, redirect from wtforms import Form from wtforms.fields import core from wtforms.fields import html5 from wtforms.fields import simple from wtforms import validators from wtforms import widgets app=Flask(__name__,template_folder='templates') #知道模板文件 app.debug=True #登陸驗證明例 class LoginForm(Form): #不一樣的字段 內部包含正則表達式 html5.EmailField | html5.DateTimeField... name=simple.StringField( label='用戶名', validators=[ #驗證規則和錯誤提示信息 validators.DataRequired(message='用戶名不能爲空.'), validators.Length(min=6, max=18, message='用戶名長度必須大於%(min)d且小於%(max)d') ], widget=widgets.TextInput(), #前端頁面顯示的插件.TextArea render_kw={'class': 'form-control'} #設置form標籤的class信息 ) # 不一樣的字段 內部包含正則表達式 html5.EmailField | html5.DateTimeField... pwd = simple.PasswordField( label='密碼', validators=[ validators.DataRequired(message='密碼不能爲空.'), validators.Length(min=8, message='用戶名長度必須大於%(min)d'), #自定義驗證規則 validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,}", message='密碼至少8個字符,至少1個大寫字母,1個小寫字母,1個數字和1個特殊字符') ], widget=widgets.PasswordInput(), render_kw={'class': 'form-control'} ) @app.route('/login/', methods=['GET', 'POST']) def login(): if request.method == 'GET': form = LoginForm() #實例化 form驗證類 return render_template('login.html', form=form) else: form = LoginForm(formdata=request.form) if form.validate(): #判斷是否驗證成功? print('用戶提交數據經過格式驗證,提交的值爲:', form.data) else: print(form.errors) return render_template('login.html', form=form) if __name__ == '__main__': app.run()
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>登陸</h1> <form method="post" novalidate> <!--<input type="text" name="name">--> <p>{{form.name.label}} {{form.name}} {{form.name.errors[0] }}</p> <!--<input type="password" name="pwd">--> <p>{{form.pwd.label}} {{form.pwd}} {{form.pwd.errors[0] }}</p> <input type="submit" value="提交"> </form> </body> </html> login.html
用戶註冊頁面驗證
#用戶註冊 from flask import Flask, render_template, request, redirect from wtforms import Form from wtforms.fields import core from wtforms.fields import html5 from wtforms.fields import simple from wtforms import validators from wtforms import widgets app = Flask(__name__, template_folder='templates') app.debug = True class RegisterForm(Form): name = simple.StringField( label='用戶名', validators=[ validators.DataRequired() ], widget=widgets.TextInput(), render_kw={'class': 'form-control'}, default='張根' #設置input標籤中默認值 ) pwd = simple.PasswordField( label='密碼', validators=[ validators.DataRequired(message='密碼不能爲空.') ], widget=widgets.PasswordInput(), render_kw={'class': 'form-control'} ) pwd_confirm = simple.PasswordField( #第二次輸入密碼 label='重複密碼', validators=[ validators.DataRequired(message='重複密碼不能爲空.'), validators.EqualTo('pwd', message="兩次密碼輸入不一致") #驗證2次輸入的密碼是否一致? ], widget=widgets.PasswordInput(), render_kw={'class': 'form-control'} ) email = html5.EmailField( label='郵箱', validators=[ validators.DataRequired(message='郵箱不能爲空.'), validators.Email(message='郵箱格式錯誤') ], widget=widgets.TextInput(input_type='email'), #生成email input標籤 render_kw={'class': 'form-control'} ) gender = core.RadioField( label='性別', choices=( #choice radio選項 (1, '男'), (2, '女'), ), coerce=int #講用戶提交過來的 '4' 強制轉成 int 4 ) city = core.SelectField( label='城市', choices=( ('bj', '北京'), ('sh', '上海'), ) ) hobby = core.SelectMultipleField( #select 下拉框多選框 label='愛好', choices=( (1, '籃球'), (2, '足球'), ), coerce=int ) favor = core.SelectMultipleField( label='喜愛', choices=( (1, '籃球'), (2, '足球'), ), widget=widgets.ListWidget(prefix_label=False), #生成Checkbox 多選框 option_widget=widgets.CheckboxInput(), coerce=int, default=[1, 2] ) def __init__(self, *args, **kwargs): #重寫form驗證類的__init__方法能夠實時同步數據中數據 super(RegisterForm, self).__init__(*args, **kwargs) self.favor.choices = ((1, '籃球'), (2, '足球'), (3, '羽毛球')) def validate_pwd_confirm(self, field): #wtforms驗證 鉤子函數 """ 自定義pwd_confirm字段規則,例:與pwd字段是否一致 :param field: :return: """ # 最開始初始化時,self.data中已經有全部的值 if field.data != self.data['pwd']: # raise validators.ValidationError("密碼不一致") # 繼續後續驗證 raise validators.StopValidation("密碼不一致") # 再也不繼續後續驗證 @app.route('/register/', methods=['GET', 'POST']) def register(): if request.method ==