flask基礎

flask基礎

一、初識flask

一、什麼是flask

Flask是一個Python編寫的Web 微框架,django個大而全的web框架,它內置許多模塊,flask是一個小而精的輕量級框架,Django功能大而全,Flask只包含基本的配置, Django的一站式解決的思路,能讓開發者不用在開發以前就在選擇應用的基礎設施上花費大量時間。Django有模板,表單,路由,基本的數據庫管理等等內建功能。與之相反,Flask只是一個內核,默認依賴於2個外部庫 Jinja2 模板引擎和 WSGI工具集--Werkzeug , flask的使用特色是基本全部的工具使用都依賴於導入的形式去擴展,flask只保留了web開發的核心功能。html

注:WSGI(web服務器網關接口)是python中用來規定web服務器如何與python Web服務器如何與Python Web程序進行溝通的標準,本質上就是一個socket服務端。而 Werkzeug模塊 就是WSGI一個具體的實現前端

二、爲何要flask

flask性能上基本知足通常web開發的需求, 而且靈活性以及可擴展性上要優於其餘web框架, 對各類數據庫的契合度都很是高python

二、如何啓動一個flask項目

一、下載flask模塊web

pip install flask

二、啓動flask項目正則表達式

# 1 導入flask,咱們要用flask,就必須導入Flask
from flask import Flask

# 2 生成一個Flask對象,__name__表示當前文件的名字
app = Flask(__name__)

# 3 添加路由,flask用的是裝飾器的模式
#註冊路由,並寫響應函數index
@app.route("/")
def index():
    return "Hello flask"

if __name__ == '__main__':
    #4 啓動flask
    #run裏面是執行了run_simple(host,port,self=app,也就是flask對象)
    app.run()

三、flask四劍客

響應函數返回的結果四種方式:返回字符串、返回HTML、跳轉路由、返回json數據庫

# 1 如何響應一個字符串
# 2 如何響應一個html頁面
# 3 如何跳轉頁面
# 4 如何返回一個json字符串

from  flask import Flask,render_template,redirect,jsonify
app = Flask(__name__)


@app.route("/index")
def index():
    #1 返回字符串
    #return "你號,我是字符串"
    
    # 2 返回一個html,
            # 1 從flask裏面導入render_template,2 在同級目錄中添加templates文件夾,將html頁面這個文件夾底下
    #return render_template("index.html")
    
    # 3 跳轉路由,1 從flask裏面導入redirect
    #return  redirect("/login")
    
    # 4 返回數據轉json返回,要從flask中導入jsonify
    data = {'name': "jason", "name1": "owen"}
    return jsonify(data)


@app.route("/login")
def login():
    return "我是login頁面"


if __name__ == '__main__':
    app.run()

四、flask配置

默認的配置:django

    default_config = ImmutableDict(
        {
            "ENV": None,
            "DEBUG": None,
            "TESTING": False,
            "PROPAGATE_EXCEPTIONS": None,
            "PRESERVE_CONTEXT_ON_EXCEPTION": None,
            "SECRET_KEY": None,
            "PERMANENT_SESSION_LIFETIME": timedelta(days=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": timedelta(hours=12),
            "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,
        }

自定義配置的幾種方式:json

一、直接給app對象加屬性flask

二、以字典的形式,給flask加配置後端

三、以文件的形式給flask加配置(Django中採用此方式)

四、以類的形式(推薦使用):在一個配置文件中多個配置,爲了減小測試與線上更改配置

from flask import Flask
app = Flask(__name__)

# 在app的下方配置flask配置
# 方式一(不推薦):直接配置app屬性,可是隻能配置兩種屬性,debug和secret_key
# app.debug = True

# 方式二:字典的形式,這個裏面就能夠配置全部的配置
# app.config['DEBUG'] = True

# 方式三:以文件的形式,在from_pyfile中傳遞文件的路徑
# app.config.from_pyfile('settings.py')

# 方式四:以類的形式(推薦使用),在一個配置文件中多個配置,爲了減小測試與線上更改配置
app.config.from_object('settings_obj.Setting')

@app.route('/')
def index():
    return "index 頁面"

if __name__ == '__main__':
    app.run()

五、路由本質以及參數

@app.route("/index") 的本質是app.add_url_rule("/index", view_func=index)因此咱們之後可使用該中方式集中管理路由

路由的參數:

  1. view_func 是賦值響應函數名
  2. endpoint 是作反向解析的,若是沒有傳遞就默認是響應函數名,反向解析用 url_for(),作解析,這個url_for必須在flask裏面導入
  3. methods=["POST", "GET"],該參數控制路由容許哪些請求方法訪問,若是不傳默認是GET方法
  4. "/index/<int:nid>"是路由以及路由轉換器,尖括號過濾類型<參數的類型:用什麼變量接收>響應函數中形參的名字要與接收的變量名一致

主要有這幾種類型過濾:

  string: 默認的數據類型,接收沒有任何斜槓"  /"的字符串

  int: 整型

  float: 浮點型

  path: 和string類型類似,可是接受斜槓,如:能夠接受參數/aa/bb/cc/多條放在一塊兒

  uuid: 只接受uuid格式的字符串字符串,

from flask import Flask,url_for,redirect
app = Flask(__name__)
# @app.route("/")
def index(nid):
    print(nid,type(nid))

    return "ojbk"

#@pp.route的本質就在執行add_url_rule這個中的rule是路由,endpoint是路由別名,view_func是響應函數
#若是endpoint不傳就是響應的函數名

app.add_url_rule("/index/<int:nid>", endpoint="index1",view_func=index,methods=["POST","GET"])

@app.route("/login",methods=["POST"])
def login():
    #用endpoint取路由要用url_for 在flask中導入,也就是反向解析
    print(url_for("index1"))
    # return  redirect(url_for("index1"))

#路由參數;methods,能夠控制該方法能有哪些請求方式能夠訪問
#app.add_url_rule("/index", endpoint="index1",view_func=index,methods=["POST"])
# 路由參數:有名分組,app.add_url_rule("/index/<int:nid>"響應函數必須用nid來接收


if __name__ == '__main__':
    app.run()

六、自定義轉換器

一、導入from werkzeug.routing import BaseConverter

二、寫個類繼承 BaseConverter ,實現3個方法,def __init__(), def to_python(), def to_url()

三、將上面的類註冊到app.url_map.converters['regex'] = RegexConverter中

四、而後就能夠在路由轉化器中使用3中的regex("傳正則")

五、當路由被訪問之後regex("傳正則")會匹配結果,把結果傳遞給to_python,咱們能夠進行再次處理,to_python處理好的結果,會傳遞給響應函數的形參

六、當用url作反向解析的時候,傳遞給路由轉換器的參數,會通過to_url,進行處理,處理之後再拼接到路由

#1 寫類,繼承BaseConverter
#2 註冊:app.url_map.converters['regex'] = RegexConverter
# 3 使用:@app.route('/index/<regex("\d+"):nid>')  正則表達式會看成第二個參數傳遞到類中

from flask import Flask, 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):
        """
        路由匹配時,匹配成功後傳遞給視圖函數中參數的值
        """
        print("to_python",value,type(value))
        return int(value)

    def to_url(self, value):
        """
        使用url_for反向生成URL時,傳遞的參數通過該方法處理,返回的值用於生成URL中的參數
        """
        val = super(RegexConverter, self).to_url(value)
        return val

# 添加到flask中
app.url_map.converters['regex'] = RegexConverter
# 正則匹配處理結果,要交給to_python,to_python函數能夠對匹配處理結果作處理
@app.route('/index/<regex("\d+"):nid>')
def index(nid):
    print("index",nid,type(nid))
    print(url_for('index', nid='888'))
    return 'Index'

if __name__ == '__main__':
    app.run()

七、flask模板渲染

from flask import Flask, render_template, Markup

app = Flask(__name__)

USERS = {
    1:{'name':'張三','age':18,'gender':'','text':"道路千萬條"},
    2:{'name':'李四','age':28,'gender':'','text':"安全第一條"},
    3:{'name':'王五','age':18,'gender':'','text':"行車不規範"},
}

def func(name):
    return Markup(f'<h1>{name}真美</h1>')

def index():
    data = {
        'user': USERS,
        'name': 'vicky'
    }
    # return render_template('index.html',**data)
    # 或者使用直接傳參數給html頁面,
    # 能夠傳遞html標籤可是html頁面須要用safe處理,或者在後端直接用Markup處理html是安全的前端能夠直接使用,
    # 也能夠傳遞一個函數給html
    return render_template('index.html',user=USERS, name='vicky', ht='<h1>vicky真美</h1>',htc = func)

app.add_url_rule('/', view_func=index)

if __name__ == '__main__':
    app.run()
<body>
<h1>index頁面</h1>
<table>
    循環取出後端傳遞user數據
    {%for k,v in user.items() %}
    <tr>
        <td>{{k}}</td>
        <td>{{v.name}}</td>
<!--        可使用[]取值-->
        <td>{{v["age"]}}</td>
<!--        可使用get取值-->
        <td>{{v.get('text')}}</td>
<!--        能夠控制路由跳轉-->
        <td>{{url_for('index')}}</td>
    </tr>
    {%endfor%}
</table>
<!--能夠直接拿到傳遞過來的name-->
<div>{{name}}</div>
<!--能夠作判斷-->
{% if name=='vicky'%}
<h1>美女</h1>
{%else%}
<h1>哈哈</h1>
{%endif%}
<!--在後端寫的html標籤,前端解析-->
{{ht|safe}}
<!--可使用函數-->
{{htc("vicky")}}
</body>

八、請求與響應

from flask import Flask, request, make_response, render_template, redirect, jsonify

app = Flask(__name__)

@app.route('/')
def index():
    # 請求相關的信息
    # print("請求方法",request.method)#請求方法
    # print("get請求的參數",request.args)# get請求的參數
    # print("post請求的參數",request.form) #post請求的參數
    # print("post,與get的全部參數",request.values)#post,與get的全部參數
    # print("請求的cookies",request.cookies)#請求的cookies
    # 請求相關信息
    # request.method  提交的方法
    # request.args  get請求說起的數據
    # request.form   post請求提交的數據
    # request.values  post和get提交的數據總和
    # request.cookies  客戶端所帶的cookie
    # request.headers  請求頭
    # request.path     不帶域名,請求路徑
    # request.full_path  不帶域名,帶參數的請求路徑
    # request.script_root
    # request.url           帶域名帶參數的請求路徑
    # request.base_url      帶域名請求路徑
    # request.url_root      域名
    # request.host_url      域名
    # request.host          127.0.0.1:5000

    # 響應相關信息
    #關於響應咱們已經將了4劍客,若是添加響應頭,已經cookie
    #要添加這些東西必須,導入make_response,
    response = make_response("ok")
    # response = make_response(render_template('index.html'))
    # response = make_response(redirect('/login'))
    # response = make_response(jsonify({"name": "zack"}))
    # 設置cookie
    response.set_cookie("k", "v")
    # 刪除cookie
    response.delete_cookie('k')
    print("請求cookies", request.cookies)
    # 設置響應頭
    response.headers['xxx']="uuu"

    return response

if __name__ == '__main__':
    app.run()

九、session設置與用法

from flask import Flask, session
# 1 導入session
app=Flask(__name__)
# 2 要用session必需要配置一個secret_key祕鑰
app.secret_key='swqe12213kewdn'


@app.route('/')
def index():
    # 3 設置session
    session['name'] = 'vicky'
    return 'ok'

@app.route('/login')
def login():
    # 4 取session值
    print(session['name'])
    return 'login'

if __name__ == '__main__':
    app.run()

session原理:

session_interface實現兩個方法設置session和取session,save_session和open_session

save_session:在返回以前經過set_cookie將session加密後存入字典中返回

response.set_cookie( app.config['SESSION_COOKIE_NAME' ,加密(session))

open_session:在取session時先經過cookie獲取大字典再對其解密獲得session

加密(session)= request.cookie("app.config['SESSION_COOKIE_NAME'")
class SecureCookieSessionInterface(SessionInterface):
   
    salt = "cookie-session"
   
    digest_method = staticmethod(hashlib.sha1)
  
    key_derivation = "hmac"
   
    serializer = session_json_serializer
    session_class = SecureCookieSession

    def get_signing_serializer(self, app):
        if not app.secret_key:
            return None
        signer_kwargs = dict(
            key_derivation=self.key_derivation, digest_method=self.digest_method
        )
        return URLSafeTimedSerializer(
            app.secret_key,
            salt=self.salt,
            serializer=self.serializer,
            signer_kwargs=signer_kwargs,
        )
    # 取session的時候執行的
    def open_session(self, app, request):
        s = self.get_signing_serializer(app)
        if s is None:
            return None
        ##cookie鍵是SESSION_COOKIE_NAME"=session
        val = request.cookies.get(app.session_cookie_name)

        print("open_session.session_cookie_name,", app.session_cookie_name, )
        if not val:
            return self.session_class()
        max_age = total_seconds(app.permanent_session_lifetime)
        try:
            data = s.loads(val, max_age=max_age)
            print("self.session_class(data)", self.session_class(data) )
            return self.session_class(data)
        except BadSignature:
            return self.session_class()

    #存session的時候執行的
    def save_session(self, app, session, response):
        domain = self.get_cookie_domain(app)
        path = self.get_cookie_path(app)

        # If the session is modified to be empty, remove the cookie.
        # If the session is empty, return without setting the cookie.
        if not session:
            if session.modified:
                response.delete_cookie(
                    app.session_cookie_name, domain=domain, path=path
                )

            return
        # Add a "Vary: Cookie" header if the session was accessed at all.
        if session.accessed:
            response.vary.add("Cookie")

        if not self.should_set_cookie(app, session):
            return
        httponly = self.get_cookie_httponly(app)
        secure = self.get_cookie_secure(app)
        samesite = self.get_cookie_samesite(app)
        expires = self.get_expiration_time(app, session)
        # 把session作了一個加密,把整個session的key--》val,所有加密,的到一個value值,
        #session是一個大字典,
        val = self.get_signing_serializer(app).dumps(dict(session))
        # 他把session加密後獲得的val存到cookie裏面了
        #cookie鍵是SESSION_COOKIE_NAME"=session
        print("源碼中的session",dict(session))
        print("app.session_cookie_name,",app.session_cookie_name,)
        response.set_cookie(
            app.session_cookie_name,
            val,
            expires=expires,
            httponly=httponly,
            domain=domain,
            path=path,
            secure=secure,
            samesite=samesite,
        )
session源碼分析

十、閃現

一、什麼是閃現

就像session同樣,也是一個頁面設置,另外一個頁面使用,我無論你在哪一個頁面調用,只能請求一次就清空了

二、爲何要用閃現

通常作信息的處理,假設用戶在a頁面操做了產生了信息,但願在b頁面獲取,無論何時獲取,但只容許拿一次,可是同一個頁面同一次請求是能夠拿屢次的

三、使用閃現

使用閃現前須要設置祕鑰 app.secret_key,導入flashget_flashed_messages

from flask import Flask, flash, get_flashed_messages

app = Flask(__name__)
app.secret_key = 'asdA'
@app.route('/')
def index():
    # 設置閃現值
    # flash('閃現值')
    # message設置消息,不寫默認傳給message,category給消息分類,在獲取的時候使用
    flash(message='閃現值', category='分類1')
    return 'index'

@app.route('/login')
def login():
    # 只能在同一次請求中獲取屢次,其餘請求都將獲取不到
    print(get_flashed_messages())  # 獲取全部的閃現值 ['閃現值']
    # with_categories=True,消息是否要帶上分類信息,category_filter=["分類1"]對消息進行過濾,取指定的分類消息
    # print(get_flashed_messages(with_categories=True, category_filter=['分類1']))  # [('分類1', '閃現值')]
    return 'login'

if __name__ == '__main__':
    app.run()
相關文章
相關標籤/搜索