1. 程式人生 > >對Python flask框架圖片分享網站的總結

對Python flask框架圖片分享網站的總結

能力

  1. 瞭解的部分:

    flask框架

     application   │ manage.py <-指令碼資料   │ runserver.py <-啟動伺服器   │   └─application <-web目錄         │ app.conf<-配置檔案         │ models.py <-資料模型         │ views.py <-檢視         │ __init__.py <-模組匯出檔案         │         ├─static <-靜態檔案         └─templates <-頁面模板                   base.html                   index.html                   login.html

    安裝模組:flask,Flask-SQLAlchemy,Flask-MySQLdb,Flask-Login,Flask-Script,nginx,gunicorn,jinjia2模板

    基礎理解:

    物件關係對映(Object-Relational Mapping):ORM

    資料模型:sql-alchemy把model的資料模型和資料庫欄位對應起來

        外來鍵(ForeignKey)始終定義在多的一方.如果relationship定義在多的一方,那就是多對一

  2. 深入瞭解的內容

    jinjia模板繼承報錯(新增jinjia環境):app.jinja_env.add_extension('jinja2.ext.loopcontrols')

    模板優勢:程式碼複用、巢狀

    內部變數傳送:

    request物件
        method:當前請求方法(POST,GET等)
        url:當前連結地址
        path:當前連結的路徑
        environ:潛在的WSGI環境
        headers:傳入的請求頭作為字典類物件
        data:包含傳入的請求資料作為
        args:請求連結中的引數(GET引數),解析後
        form:form提交中的引數,解析後
        values:args和forms的集合
        json:json格式的body資料,解析後
        cookies:cookie讀取
     response物件
        response = make_response(render_template(index.html))  
            方法
        status:響應狀態
        headers:響應頭,設定http欄位
        set_coockie:設定一個cookie
    
    網頁渲染引擎:
    

            在Flask中我們把這一工作叫做渲染模板,其中我們準備好的網頁叫做模板,渲染工作交給一個叫做jinja2模板引擎就好了,具體使用方法是呼叫函式render_template('檔名')

            我們所要渲染的所有模板都需要放在templates資料夾下,所以我們需要新建一個templates資料夾並將我們準備好的HTML檔案放進去,在這裡我們把它叫做test.html

            到了這裡關於HTML的準備工作就完成了,接下來就是使用flask渲染模板

     我們在與templates同一目錄下新建一個main.py檔案,寫下如下程式碼即可

    from flask import Flask,render_template app = Flask(__name__) @app.route('/test') def test():     return render_template('test.html')  if __name__ == '__main__':     app.run()  

        可以看到我們例項化了一個Flask物件併為它定義了一個路由,當訪問地址為/test時使用render_template渲染模板test.html

  3. 橫向發展如何舉一反三
    做完專案之後,思考spring框架的整體結構怎麼樣?spring框架都用了哪些技術,其他框架怎麼渲染,內部變數怎麼傳的

潛力

  1. 如何解決問題
    發現使用jinjia2的時候會報錯,說明配置裡面沒有加jinjia2的使用環境,(----------------->舉一反三)
  2. 怎麼舉一反三
    讓我想起了以前的XXX框架也是出現了類似問題,我是如何解決的
  3. 如何優化專案

    如何優化這個專案:

    前端程式碼儘可能了壓縮減少頻寬

    1. Web伺服器開啟Gzip壓縮

    在HTTP協議中允許客戶端可以選擇從伺服器上下載壓縮的內容,Gzip就是其中一種支援的格式。

    2. JavaScript程式碼壓縮

    JavaScript壓縮的原理一般是去掉多餘的空格和回車、替換長變數名、簡化一些程式碼寫法等。

    3. CSS程式碼壓縮

    CSS程式碼壓縮原理和JavaScript程式碼壓縮的原理類似,也是去掉不必要的空格回車註釋等,並同時優化合並一些CSS規則定義,讓規則更簡潔。

    4. HTML程式碼壓縮

    壓縮HTML程式碼的爭議很大,反對的一方覺得壓縮的作用不大,不像壓縮JavaScript和CSS程式碼,壓縮HTML程式碼僅僅是去掉空格回車註釋等無關字元,並不會簡化HTML程式碼本身,所以覺得在伺服器開啟Gzip就足夠了。

    5. 圖片資源壓縮

    除了程式碼的壓縮外,網頁中使用最多的資原始檔就是圖片,在一般的網站中,圖片資源佔有的比重還是挺大的。圖片壓縮工具主要是線上工具和本地應用程式,還沒有好一點的編輯器外掛可用。好在一般專案中,圖片的變化並不是很大,所以圖片的自動化壓縮工具的需求並不是很迫切。

    降低併發:

    【使用快取】

      使用cach-control或expires這類強快取時,快取不過期的情況下,不向伺服器傳送請求。當快取過期時,會使用last-modified或etag這類協商快取,向伺服器傳送請求,如果資源沒有變化,則伺服器返回304響應,瀏覽器繼續從本地快取載入資源;如果資源更新了,則伺服器將更新後的資源傳送到瀏覽器,並返回200響應

  4. 怎麼快速學習
            完整閱讀一篇官方文件,從中學習框架等技術的整體框架,其他技術的學習都是一樣的。

分析

網站

  1. 許可權管理

    1. 驗證欄位與密碼的儲存

    許可權管理的基礎就是驗證欄位(使用者名稱or郵箱...)以及密碼, 所以首先需要考慮驗證欄位和密碼的儲存。(這裡使用flask-sqlalchemy作為ORM)

    2. 使用者許可權與角色的設定

    我一般將使用者許可權設定為16進位制的值, 而使用者角色則是使用者許可權(16進位制的值)的異或(|)運算,

    那麼可設定如下角色, 並建立和User的多對一關係

    現在只需在User裡建立一個指向使用者角色的外來鍵即可

    flask許可權在具體場景中的應用

    應用在具體場景, 使用相關擴充套件就不可避免了

    1. 處理登入(flask-login)

    對於flask登入,使用flask-login是較為簡單的辦法, 但是個人感覺flask-login不是很靈活(下面的擴充套件也是, 畢竟擴充套件的目的是通用)。 這裡就不具體說明如何整合flask-login了,主要說如何使用flask-login

    使用者登入

    使用flask-login提供的login_usercurrent_user

    使用者登出

    使用flask-login提供的logout_user

    2. 處理HTTPBasicAuth(flask-httpauth)

    flask-httpauth 可以幫助我們處理一些基本的許可權管理, 同flask-login一樣, flask-httpauth 也提供了一個login_required裝飾器, 通過auth物件呼叫即可控制使用者名稱, 密碼的登入許可權控制。

    token許可權管理

    這裡比較複雜的地方就是token的許可權管理了, 因為此處沒有拓展可用(擴充套件是為了通用性, 但是token不是強制使用的), 都是自己踩坑弄出來的, 寫在部落格裡做一個紀錄。

    什麼是token

    token是使用者資訊(一般是使用者id, 具有唯一標識作用)的標識。對使用者id進行簽名加密(我一般使用itsdangerous模組),

    為什麼需要token?

    token 一般使用在API的場景中, 此時客戶端和伺服器端是分離的, 資料資訊通過API進行傳遞, 他人很容易就可以攔截API並獲取驗證頭部的authorization欄位, 從而獲取使用者名稱和密碼(一般是base64進行了加密, 但是很容易被破解), 這樣是極不安全的。 之所以需要驗證, 其實就是為了標識這個使用者是誰, 而id就是一個最好的標識, 所以通過使用者的使用者名稱和密碼請求token(這樣使用者名稱和密碼不會頻繁被髮送), 用獲取的token放在API頭部進行傳遞, 這樣即使被攔截, 也不會獲取使用者的敏感資訊(使用者名稱, 密碼), 即使token被他人使用, 也會因為token的壽命而使破壞性大大降低。

    token的使用: 傳送token

    token需放在Authorization頭部, 採用如下形式傳送:

    token的使用: 解析token

    依然採用itsdangerous模組, 這裡金鑰就很重要了, 只有與加密相同的金鑰才可以解析token。

    基於token的許可權管理

    這裡主要是區別普通使用者和管理員使用者, 因為有些特定的操作是隻有管理員可以進行的。

    1.在User類裡新增管理員判斷函式 

    2.建立管理員許可權判斷裝飾器

    然後就可以使用admin_required裝飾器進行許可權管理了, 這裡有個坑提一下就是flask-httpauth會自己新增Basic, 所以使用該擴充套件的地方就不必考慮token格式的問題了。

  2. 資料庫安全

    salt給密碼加鹽然後再加密儲存到資料庫中

    單點登入

    驗證碼機制防止爆破

    郵箱/簡訊驗證(使用者有一箇中間狀態)

    User使用者介面     is_authenticated     is_active     is_anonymous     get_id()

    核心函式和屬性     login_user(user)     logout_user()     login_required     current_user

演算法

 解決思路和靈感來源

關注網站的上網時間節點,來提高廣告的點選率----->這時候可以舉一反三,提高對使用者性別的關注來提高廣告的點選率

後記

多執行緒技術:

Thread 是threading模組中最重要的類之一,可以使用它來建立執行緒。有兩種方式來建立執行緒:

        一種是通過繼承Thread類,重寫它的run方法;

        另一種是建立一個threading.Thread物件,在它的初始化函式(__init__)中將可呼叫物件作為引數傳入.

        Thread模組是比較底層的模組,Threading模組是對Thread做了一些包裝的,可以更加方便的被使用。

併發技術:

        redis,資料結構,非同步,容錯機制

redis處理高併發思路:

使用者在下訂單之前當然是先查詢到這個商品,在這個查詢的時候,將資料庫中商品的剩餘數量存到redis中;

伺服器在一瞬間接到成千上萬的下訂單請求,在控制層沒有直接處理請求資料,而是先根據redis中商品的剩餘數量來判斷,如果>0,就將請求放到請求佇列中,否則直接響應客戶端“賣完了”;

考慮到資料的一致性,佇列的容量就是商品的剩餘數量,佇列採用的是執行緒安全的佇列LinkedBlockingQueue(單臺伺服器),然後通過新的執行緒非同步處理這些請求,多臺伺服器的話,可以考慮使用訊息佇列MQ,單獨用一臺伺服器去處理訊息佇列中的請求;

客戶端傳送訂單請求之後,會收到響應,要麼是剩餘數量不足(賣完了),要麼是請求已經被放到佇列中,為下一步的輪詢訂單做準備;

如果響應狀態是賣完了,直接提示客戶,如果請求已經放入佇列中,就可以根據使用者id和商品id去輪詢訂單了;