標籤:網站後端 python flask
網域名稱設定:
說明: SERVER_NAME內建屬性的設定會影響全域URL,它主要有兩個作用,第一個作用是在請求上下文之外產生絕對URL,當然如果設定也會影響請求上下文內的絕對URL,第二個作用是用於子網域名稱的支援
#!/usr/bin/env python# -*- coding: utf-8 -*-"""## Authors: limanman# 51CTOBG: http://xmdevops.blog.51cto.com/# Purpose:#"""# 說明: 匯入公用模組from flask import Flask, url_for# 說明: 匯入其它模組app = Flask(__name__)# app.url_map.default_subdomain=‘www‘# app.config.update(SERVER_NAME=‘blog.51cto.com‘)with app.test_request_context(): print ‘found notice: with request context full url is: %s‘ % ( url_for(‘static‘, filename=‘css/style.css‘, _external=True), )with app.app_context(): print ‘found notice: with app context full url is: %s‘ % ( url_for(‘static‘, filename=‘css/style.css‘, _external=True), )if __name__ == ‘__main__‘: app.run(host=‘0.0.0.0‘, port=9000, debug=True)
說明: 如上代碼在沒有設定SERVER_NAME預設屬性時,直接運行會報RuntimeError: Application was not able to create a URL adapter for request independent URL generation. You might be able to fix this by setting the SERVER_NAME config variable.說明url_for是依賴請求內容相關的,若要產生不依賴於請求上下文(也就是說在請求上下文或程式上下文),最常見的就是非同步發送郵件時url_for產生的郵件中的地址時就必須設定SERVER_NAME
子域實現:
說明: SERVER_NAME還用於子網域名稱,因為FLASK在得知現有伺服器名之前不能猜測出子網域名稱部分,在請求上下文中如果沒有設定SERVER_NAME,預設使用request.host,但是一旦設定SERVER_NAME,將全域影響全URL的主機部分,所以為了讓FLASK以.分割識別子網域名稱,強烈建議設定SERVER_NAME為指定網域名稱,且指定名稱的時候一定是SERVER_NAME=‘blog.51cto.com:9000‘主網域名稱加連接埠的形式,不然不會生效,如下就簡單示範下常規項目開發中子網域名稱的使用以及隔離資源檔及模版的方法,由於代碼量有點多,就直接上傳代碼講解
: http://1000eb.com/1kw8v
.│ main.py│├─app│ │ prod_config.py│ │ test_config.py│ │ __init__.py│ ││ ├─monitor│ │ │ api.py│ │ │ views.py│ │ │ __init__.py│ │ ││ │ ├─static│ │ │ └─js│ │ │ main.js│ │ ││ │ └─templates│ ├─static│ └─templates├─bin└─doc
1. main.py為入口檔案,調用app包下的create_app函數建立app執行個體,然後調用app.run來啟動執行個體
2. prod_config.py中為生產環境配置,再本地測試環境嘗試匯入test_config.py為當前配置,SERVER_NAME就在test_config.py中聲明的,發布生產環境時刪掉test_config.py即可
3. monitor包中定義了monitor藍圖,建立藍圖時指定subdomain=‘monitor‘,使得我們訪問monitor.blog.51cto.com時會自動訪問monitor藍圖,但是需要注意的是視圖函數或是模版中使用url_for()產生路徑時強烈推薦加上藍圖名,如上url_for(‘.static‘, filename=‘js/main.js‘, _external=True)/url_for(‘monitor.static‘, filename=‘js/main.js‘, _external=True)產生的是http://monitor.blog.51cto.com/static/js/main.js,對應的檔案是app/monitor/static/js/main.js檔案,而url_for(‘static‘, filename=‘js/main.js‘, _external=True)則產生的是http://blog.51cto.com/static/js/main.js,試圖訪問必然無法訪問,一般遇到這種問題,可以用NGINX前端REWRITE重寫下URL加一個預設子網域名稱,如www即可解決
4. create_app函數主要載入prod_config.py中的配置,以及註冊monitor包中的monitor藍圖
通配子域:
說明: 有時需要一個藍圖匹配多個子網域名稱,比如51CTO給每個註冊使用者指派一個性網域名稱類似http://xmdevops.blog.51cto.com/,且每個使用者有自己的首頁,以及不同的資訊展示頁面,此時就可以用動態URL
#!/usr/bin/env python# -*- coding: utf-8 -*-"""## Authors: limanman# OsChina: http://xmdevops.blog.51cto.com/# Purpose:#"""# 說明: 匯入公用模組from flask import Blueprint, g# 說明: 匯入其它模組monitor = Blueprint(‘monitor‘, __name__, subdomain=‘<subdomain>‘, static_folder=‘static‘, template_folder=‘templates‘)@monitor.url_value_preprocessordef set_site(endpoint, values): g.subdomain = values.pop(‘subdomain‘, None)@monitor.url_defaultsdef get_site(endpoint, values): values.update(‘subdomain‘, g.subdomain)@monitor.before_requestdef get_user(): # g.user = WebUser.query.filter_by(name=g.subdomain).first_or_404() g.user = g.subdomain if g.subdomain else Nonefrom . import apifrom . import views
說明: 在之前的代碼上僅此修改了app/monitor/__init__.py中的代碼,在建立藍圖時候修改參數subdomain=‘<subdomain>‘,其實就是利用字串轉換器,我們希望輸入不同的使用者名稱子網域名稱跳轉到不同的使用者首頁,如上代碼用到了LocalThread對象g,基於線程隔離的對象,如當訪問http://user1.blog.51cto.com:9000時,由於我們DNS已經做了泛解析,指向了127.0.0.1(直接hosts檔案添加類比),所以request.host的值被置為user1.blog.51cto.com:9000,由於我們app.url_map.default_subdomain設定的為‘blog.51cto.com:9000‘且建立monitor藍圖時指定了subdomain=‘<subdomain>‘,正好匹配子網域名稱的形式,所以將subdomain的值通過current_app.url_map.converts中的轉換器轉換後分別傳給視圖函數和內部編碼後的URL,但是我們希望在傳遞給視圖函數之前擷取subdomain並存放到LocalThread g對象中以便線程隔離訪問,FLASK為我們提供了monitor.url_defaults和monitor.url_value_preprocessor兩個裝飾器,兩者都調用一個接收endpoint, values的函數,endpoint其實就是藍圖,values儲存的是這個藍圖下的URL中動態名稱和動態內容的映射關係(如subdomain: subdomain值),monitor.url_value_preprocessor會在轉換資料後將資料從subdomain中彈出賦值給g對象,但是如果你此時直接存取的話坑定會報錯說少參數,因為你把subdomain彈出了~,所以url_defaults的作用就是等URL處理完前期轉換以及值處理後重新將值更新進去,最後在monitor.before_request處理請求之前將子網域名稱換為使用者物件~ 至於剩下的事情就是渲染頁面了~
本文出自 “@Can Up and No BB...” 部落格,請務必保留此出處http://xmdevops.blog.51cto.com/11144840/1866989
網站後端_Python+Flask.0012.FLASK網域名稱相關之網域名稱與動態子網域名稱實現?