python3-開發進階Flask的基礎

 1、概述

最大的特色:短小精悍、可拓展強的一個Web框架。注意點:上下文管理機制,依賴wsgi:werkzurg 模塊html

2、前奏學習werkzurg

先來回顧一個知識點:一個類加括號會執行__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>

3、Flask

一、簡介

一、配置文件                                                                                           

    模塊+靜態文件         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中是什麼的格式呢?

  • @duo.route('/user/<username>')      字符串
  • @duo.route('/post/<int:post_id>')      整數
  • @duo.route('/post/<float:post_id>')    浮點
  • @duo.route('/post/<path:path>')       路徑
  • @duo.route('/login', methods=['GET', 'POST'])

可是默認是不支持正則!   

這就是動態的路由

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 '沒找到'    #定製錯誤信息的頁面比較經常使用
相關文章
相關標籤/搜索