最大的特色:短小精悍、可拓展強的一個Web框架。注意點:上下文管理機制,依賴wsgi:werkzurg 模塊html
先來回顧一個知識點:一個類加括號會執行__init__方法,一個對象加括號執行__call__方法前端
事例1:python
from werkzeug.wrappers import Request, Response @Request.application def hello(request): return Response('Hello World!') if __name__ == '__main__': from werkzeug.serving import run_simple run_simple('localhost', 4000, hello) #封裝了請求和相應的對象
flask就是基於上面一步一步搭建起來的!django
3、學習flaskjson
第一個flask:flask
from flask import Flask duo=Flask(__name__) duo.run()
三行 啓動了程序,可是訪問url,發現是Not Found !!!後端
什麼緣由呢?按理說訪問url,執行函數,返回結果,咱們發現咱們訪問了,可是沒有接收,在django應該怎麼寫,寫個路由寫個視圖,在這也是同樣安全
from flask import Flask duo=Flask(__name__) @duo.route('index') def index(): return "hello world" duo.run() #這下執行就訪問成功
這個duo.run 就是啓動socket,這個腳本要以主函數去運行的時候,採起執行duo.run,別人若是導入的時候,run是不該該執行的:cookie
from flask import Flask duo=Flask(__name__) @duo.route('index') def index(): return "hello world" if __name__ == '__main__': duo.run()
一個flasl實現簡單的登陸:session
from flask import Flask,render_template,request,redirect,session duo=Flask(__name__) duo.secret_key='shuai' #加密方式 @duo.route('/login',methods=['GET','POST']) #默認GET 別的請求還要添加 def login(): if request.method == 'GET': #return 'Login' #HttpResponse django 返回字符串 return render_template('login.html') #request.form ----------》#request.POST #request.args ----------》 #request.GET user=request.form.get('user') pwd=request.form.get('pwd') if user=='duoduo' and pwd =='123': session['user']=user return redirect('/index') return render_template('login.html',error='用戶名或密碼錯誤') @duo.route('/index') def index(): user=session.get('user') if not user: return redirect('login') return render_template('index.html') if __name__ == '__main__': duo.run()
login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> <h1>用戶登入</h1> <form method="post"> <input type="text" name="user"> <input type="password" name="pwd"> <input type="submit" value="提交">{{error}} </form> </body> </html>
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> <h1>歡迎使用</h1> <img src="/static/111.jpg" alt=""> #圖片本身找個 </body> </html>
一、配置文件
模塊+靜態文件 Flask(__name__,...)
二、路由系統 裝飾器實現的
@duo.route('/index',methods=['GET'])
三、視圖 也有fbv,cbv
四、請求相關 導入就能用,django 而是參數
request.form
request.args
request.method
五、響應
字符串‘’
render
redirect
六、模塊渲染
七、session
session['xxx']=123
session.get('xxx')
八、fiash (閃現)
九、中間件 基本不用 請求前的操做
十、特殊的裝飾器
假使一個setting.py:
class Foo: DEBUG=True TEST=True
一個腳本duoduo.py
path='setting.Foo'
咱們如何在path中將Foo這個類找到?如何獲取其中大寫的靜態字段的值:
import importlib path='setting.Foo' p,c=path.rsplit('.',maxsplit=1) m=importlib.import_module(p) cls=getattr(m,c) for key in dir(cls): if key.isupper(): print(key,getattr(cls,key)) #其實這就是配置文件導入原理
一、配置文件
flask的配置文件在哪裏呢?這些都是默認的配置文件,
from flask import Flask duo=Flask(__name__) print(duo.config) #<Config {'ENV': 'production', 'DEBUG': False, 'TESTING': False, 'PROPAGATE_EXCEPTIONS': None,
'PRESERVE_CONTEXT_ON_EXCEPTION': None, 'SECRET_KEY': None, 'PERMANENT_SESSION_LIFETIME': datetime.timedelta(31),
'USE_X_SENDFILE': False, 'SERVER_NAME': None, 'APPLICATION_ROOT': '/', 'SESSION_COOKIE_NAME': 'session',
'SESSION_COOKIE_DOMAIN': None, 'SESSION_COOKIE_PATH': None, 'SESSION_COOKIE_HTTPONLY': True,
'SESSION_COOKIE_SECURE': False, 'SESSION_COOKIE_SAMESITE': None, 'SESSION_REFRESH_EACH_REQUEST': True,
'MAX_CONTENT_LENGTH': None, 'SEND_FILE_MAX_AGE_DEFAULT': datetime.timedelta(0, 43200), 'TRAP_BAD_REQUEST_ERRORS': None,
'TRAP_HTTP_EXCEPTIONS': False, 'EXPLAIN_TEMPLATE_LOADING': False, 'PREFERRED_URL_SCHEME': 'http', 'JSON_AS_ASCII': True,
'JSON_SORT_KEYS': True, 'JSONIFY_PRETTYPRINT_REGULAR': False, 'JSONIFY_MIMETYPE': 'application/json',
'TEMPLATES_AUTO_RELOAD': None, 'MAX_COOKIE_SIZE': 4093}>
配置文件是能夠修改的,那在哪裏改?咱們這有這樣一個語法:
duo.config.from_object('setting.Foo') #仍是上面的setting.py文件
咱們來看看.from_object 中的源碼:
咱們之後的配置文件,能夠生成不同的類,開發環境一個類,線上環境一個類,相同的靜態屬性一個類,咱們根據現實的環境只需改一個類名字就能夠了
二、路由系統
@duo.route(url,methods(容許請求的方式),endpoint(值))
-endpoint ,反向生成URL,若是沒有endpoint設定的值,那麼默認的這就是函數名
-url_for('endpoint設定的值')
from flask import Flask,url_for duo=Flask(__name__) # print(duo.config) duo.config.from_object('setting.Foo') # print(duo.config) @duo.route('/index/',methods=['GET','POST']) #endpoint就是django反向生成的name,若是不寫endpoint,url_for後面的值就是函數名 def index(): print(url_for('index')) #反向生成url return "hello world" if __name__ == '__main__': duo.run()
咱們在django中有的時候url會帶上對象的nid值,這個在flask中是什麼的格式呢?
可是默認是不支持正則!
這就是動態的路由
from flask import Flask,url_for duo=Flask(__name__) # print(duo.config) duo.config.from_object('setting.Foo') # print(duo.config) @duo.route('/index/<int:nid>',methods=['GET','POST']) #int是用來約束在url的值 def index(nid): print(nid) print(url_for('index',nid=1)) #有參數要加參數 return "hello world" if __name__ == '__main__': duo.run()
三、FBV(CBV後面再介紹)
四、請求相關,響應相關
from flask import Flask,jsonify,make_response duo=Flask(__name__) @duo.route('/index/<int:nid>',methods=['GET','POST']) #int是用來約束在url的值 def index(nid): # 請求相關信息 # request.method # request.args # request.form # request.values # request.cookies # request.headers # request.path # request.full_path # request.script_root # request.url # request.base_url # 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))
# 響應相關信息 # return "字符串" # return render_template('html模板路徑',**{}) # return redirect('/index.html') # return jsonify({'k1':'v1'}) #jsonify幫你序列化 obj=make_response('Index') #把返回給用戶的字符串,封裝到這個對象 obj.headers['duoduo']=666 #設置響應頭 return obj if __name__ == '__main__': duo.run()
運行後:
六、模板的渲染
一個登入驗證,能夠導入before_request,沒有返回值就是能夠經過,有返回值就沒法經過
from flask import Flask,request,before_request,session duo=Flask(__name__) @duo.before_request def xxxxx(): if request.path =='/login': #只有登入視圖能夠訪問 return None if session.get('user') : return None return redirect('login') # 上面不經過,返回登入頁面
-基本數據類型:能夠執行python的語法,如:dict.get() list['xx']
-傳入函數
django,自動執行
flask,不自動執行
-全局定義函數
@duo.template_global()
@duo.template_filter()
-模板的繼承
{%extends '給誰'%}
{%block content%}
{% endblock%}
-include 直接加頁面
-安全方式展現
前端:{{obj|safe}}
後端:Markup('obj')
七、session
session在視圖中能夠字典來使用,爲何能看成字典,咱們來看一下源碼:
from flask.sessions import SecureCookieSession
繼承了dict,不用多說什麼
當請求剛進來時:flask讀取cookie中session對應的值:將這個值解密並反序列化成字典,放入內存,以便視圖函數使用,
當請求結束時:flask會讀取內存中字典的值,在進行序列化+加密,寫入到用戶的cookie中。(這就是session的機制)
session的配置是能夠改的,關於session有如下幾點:
'PERMANENT_SESSION_LIFETIME': timedelta(days=31), #生命週期 'SESSION_COOKIE_NAME': 'session' #名稱 'SESSION_COOKIE_DOMAIN': None #域名 'SESSION_COOKIE_PATH': None #路徑 ‘SESSION_COOKIE_HTTPONLY': True #支持HP讀取 'SESSION_COOKIE_SECURE': False #安全性 'SESSION_REFRESH_EACH_REQUEST': True #最後一次訪問的時間保持
八、flash
在session中存儲一會數據,讀取時經過pop將數據移除,以此來創造一個效果,只存一次,只能取一次
實例:
from flask import Flask,flash,get_flashed_messages duo=Flask(__name__) duo.secret_key='duoduo' #這是一個容易忘記的點 #出現secret_key 的報錯就是這個設置 @duo.route('/page1') def page1(): flash('大娃','boy') flash('二娃','boy') flash('蛇精','girl') return 'session' @duo.route('/page2') def page2(): print(get_flashed_messages(category_filter=['boy'])) return 'session' if __name__ == '__main__': duo.run()
訪問一下,取一下,咱們來看看源碼:
九、中間件
那咱們先來了解一下flask是怎麼運行起來的:
先寫一個簡單的腳本:
from flask import Flask duo=Flask(__name__) @duo.route('/index') def index(): print('index') return 'Index' if __name__ == '__main__': duo.run()
首先,先點開源碼的duo.run:
run的self就是flask的對象,請求進來第三給參數後面加括號,是否是flask的對象加括號,就是調用,對象調用執行__call__方法:
duo.__call__ #進去看看
當上面的腳本運行,只有請求訪問,才執行__call__方法
一個簡單的應用
from flask import Flask duo=Flask(__name__) @duo.route('/index') def index(): print('index') return 'Index' class Middleware(object): def __init__(self,old): self.old=old def __call__(self, *args, **kwargs): print('執行前') ret=self.old(*args,**kwargs) print('執行後') return ret if __name__ == '__main__': duo.wsgi_app=Middleware(duo.wsgi_app) duo.run()
十、特殊的裝飾器(重點)
before_request #誰先定義執行
after_request #從後往上執行
這上面兩個原理就是把函數名放到一個列表,而後循環的機制
from flask import Flask duo=Flask(__name__) @duo.before_request def x1(): print('before') @duo.after_request def x2(reponse): #這裏必需要有返回值 print('after') return reponse @duo.route('/index1') def index1(): print('index') return 'Index' @duo.route('/order') def order(): print('order') return 'order' if __name__ == '__main__': duo.run()
這裏有一個注意點就是,before_request有返回值的話,要走全部的after_request ,在django1.9之前都只是這個流程,後來改了機制,
咱們發現1.10之後,走最外面一箇中間件就返回。
before_first_request #只執行啓動起來 首次,後就再也不執行,後面詳細看源碼
template_global # 渲染 全局定義函數
template_filter # 不同的全局定義函數
errorhandler #定製錯誤信息
@duo.errorhandler(404) def not_found(arg): print(arg) return '沒找到' #定製錯誤信息的頁面比較經常使用