<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
建立完成後整個專案結構樹:
app.py: 項⽬管理⽂件,通過它管理項⽬。
static: 存放靜態檔案
templates資料夾:用於放置html模板檔案
由於flask屬於輕量級web框架, 更加自由、靈活,可延伸性強,第三方庫的選擇面廣,開發時可以結合自己最喜歡用的輪子,也能結合最流行最強大的Python庫 。所以這個框架的程式碼架構需要自己設計。
手動建立application目錄、filter目錄及其子目錄
application : 專案主要邏輯程式碼儲存目錄
_init_.py : 建立flask應用並載入設定,如mysql,redis,rabbitmq,
apps : 專門用於儲存每一個專案的藍圖
app1 : app1藍圖目錄,在app1下的init_.py中檔案中建立藍圖物件,view.py中新增對應的檢視檔案,在 model.py中寫模型程式碼
settings : 專案設定儲存目錄
dev.py : 專案開發階段組態檔
prop.py : 專案生成階段組態檔
static : 專案靜態資料夾(用於存放css一類的檔案)
templates : 用於放置html模板檔案
filter : 整個專案攔截器目錄
requestFilter.py: 針對整個app專案全域性路由攔截規則定義
app.py : 項⽬管理⽂件,通過它啟動整個專案
2.1.1 settings.py
#全域性通用設定類 class Config(object): """專案設定核心類""" #偵錯模式 DEBUG=False # 設定紀錄檔 # LOG_LEVEL = "DEBUG" LOG_LEVEL = "INFO" # 設定redis # 專案上線以後,這個地址就會被替換成真實IP地址,mysql也是 REDIS_HOST = 'your host' REDIS_PORT = your port REDIS_PASSWORD = 'your password' REDIS_POLL = 10 #資料庫連線格式 SQLALCHEMY_DATABASE_URI = "mysql+pymysql://user:password@localhost:3306/test?charset=utf8" # 動態追蹤修改設定,如未設定只會提示警告 SQLALCHEMY_TRACK_MODIFICATIONS = False # 查詢時會顯示原始SQL語句 SQLALCHEMY_ECHO = False # 資料庫連線池的大小 SQLALCHEMY_POOL_SIZE=10 #指定資料庫連線池的超時時間 SQLALCHEMY_POOL_TIMEOUT=10 # 控制在連線池達到最大值後可以建立的連線數。當這些額外的 連線回收到連線池後將會被斷開和拋棄。 SQLALCHEMY_MAX_OVERFLOW=2 #rabbitmq引數設定 RABBITUSER="user" RABBITPASSWORD="password" RABBITHOST="your ip" RABBITPORT=your port
2.1.2 dev.py
from . import Config class DevelopmentConfig(Config): '開發模式下的設定' # 查詢時會顯示原始SQL語句 SQLALCHEMY_ECHO = True
2.1.3 prop.py
from . import Config class ProductionConfig(Config): """生產模式下的設定""" DEBUG = False
2.1.4 載入組態檔,定義全域性的db( SQLALchemy類的範例 )供專案使用
# 主應用的根目錄 app = Flask(__name__) config = { 'dev': DevelopmentConfig, 'prop': ProductionConfig, } # 設定設定類 Config = config['dev'] # 載入設定 app.config.from_object(Config) # 建立資料庫連線物件 db = SQLAlchemy(app)
dev : 測試環境設定
prop: 生產環境設定
Flask應用app設定載入
通常三種方式
設定物件
從設定物件中載入,建立設定的類:
# 設定物件,裡面定義需要給 APP 新增的一系列設定 class Config(object): DEBUG = True app = Flask(__name__) # 從設定物件中載入設定 app.config.from_object(Config) app.run()
組態檔
從組態檔中載入,在目錄中定義一個組態檔config.ini
app = Flask(__name__) # 從設定物件中載入設定 app.config.from_pyfile("config.ini") app.run()
環境變數
app = Flask(__name__) # 從環境變數中載入 app.config.from_envvar("FLASKCONFIG") app.run()
app1.model
from application import db class Wdtest(db.Model): __tablename__ = "wdtest" #設定表名 id = db.Column(db.String(100), primary_key=True, comment="主鍵ID") name = db.Column(db.String(20), index=True, comment="姓名" ) age = db.Column(db.Integer, default=True, comment="年齡")
模型 表示程式使用的持久化實體. 在Flask-SQLALchemy 中, 模型一般是一個 Python 類, 類中的屬性對應資料庫中的表.
db.Model :建立模型,
db.Column : 建立模型屬性.
tablename :指定表名
模型屬性型別 :
型別名 | Python型別 | 說明 |
---|---|---|
Integer | int | 普通整數,一般是 32 位 |
SmallInteger | int | 取值範圍小的整數,一般是 16 位 |
Big Integer | int 或 long | 不限制精度的整數 |
Float | float | 浮點數 |
Numeric | decimal.Decimal | 定點數 |
String | str | 變長字串 |
Text | str | 變長字串,對較長或不限長度的字串做了優化 |
Unicode | unicode | 變長 Unicode 字串 |
Unicode Text | unicode | 變長 Unicode 字串,對較長或不限長度的字串做了優化 |
Boolean | bool | 布林值 |
Date | datetime.date | 日期 |
Time | datetime.time | 時間 |
DateTime | datetime.datetime | 日期和時間 |
Interval | datetime.timedelta | 時間間隔 |
Enum | str | 一組字串 |
PickleType | 任何 Python 物件 | 自動使用 Pickle 序列化 |
LargeBinary | str | 二進位制檔案 |
常用 SQLAlchemy 列選項
選項名 | 說明 |
---|---|
primary_key | 如果設為 True,這列就是表的主鍵 |
unique | 如果設為 True,這列不允許出現重複的值 |
index | 如果設為 True,為這列建立索引,提升查詢效率 |
nullable | 如果設為 True,這列允許使用空值;如果設為 False,這列不允許使用空值 |
default | 為這列定義預設值 |
app1._init.py
#給app取別名為 'index' index_blu=Blueprint('index',__name__,template_folder='templates',static_folder='static') from .views import *
template_folder:指定模板檔案路徑,查詢順序,先全域性templates裡面找,沒找到,再往子藍圖裡面找.
這裡是把view中所有的檢視都宣告在index這個藍圖裡面,接下來我們需要做的是將這個宣告好的藍圖,註冊進我們的專案中。
application.init_:
from application.settings.dev import DevelopmentConfig from application.settings.prop import ProductionConfig # 主應用的根目錄 app = Flask(__name__) config = { 'dev': DevelopmentConfig, 'prop': ProductionConfig, } # 設定設定類 Config = config['dev'] # 載入設定 app.config.from_object(Config) # 建立資料庫連線物件 db = SQLAlchemy(app) # todo 註冊藍圖 from .apps.app1 import index_blu app.register_blueprint(index_blu, url_prefix='/index')
針對:app = Flask(name)解釋
Flask類初始化引數
Flask類init方法部分程式碼
def __init__( self, import_name, static_url_path=None, static_folder="static", static_host=None, host_matching=False, subdomain_matching=False, template_folder="templates", instance_path=None, instance_relative_config=False, root_path=None, ):pass
import_name:Flask程式所在的包(模組),傳 __name__
static_url_path:靜態檔案存取路徑,可以不傳,預設為:/ + static_folder
static_folder:靜態檔案儲存的資料夾,可以不傳,預設為 static
template_folder:模板檔案儲存的資料夾,可以不傳,預設為 templates
以下所有範例程式碼,皆在view.py中去實現
3.1 增:
先寫怎麼增,然後增加,最後提交
student = Wdtest(id=ids , name=name, age=age) try: application.db.session.add(student) application.db.session.commit() except: # 事務回滾 application.db.session.rollback()
3.2 刪:
先獲取資料庫中的這個資料,再刪除它
user = Wdtest.query.first() application.db.session.delete(user) application.db.session.commit()
3.3 改:
user = Wdtest.query.first() user.name = name try: application.db.session.commit() except: # 事務回滾 application.db.session.rollback()
3.4 查:
# 查詢所有⽤戶資料 user_list=Wdtest.query.all() # 查詢有多少個⽤戶 user_list_num=Wdtest.query.count() # 查詢第1個⽤戶 user=Wdtest.query.first() # 查詢id為3的⽤戶[3種⽅式] user=Wdtest.query.get(3) # 根據主鍵查詢 user_list=Wdtest.query.filter_by(id=3).all() # 以關鍵字實參形式進行匹配欄位 user_list=Wdtest.query.filter(Wdtest.id == 3).all() # 以恆等式形式匹配欄位 # 查詢名字結尾字元為g的所有⽤戶 Wdtest.query.filter(Wdtest.name.endswith('g')).all() # 查詢名字包含‘wa'的所有專案 user_list=Wdtest.query.filter(Wdtest.name.contains('wa')).all() # 模糊查詢 user_list =Wdtest.query.filter(Wdtest.name.like('%a%')).all() # 查詢名字wa開頭和age為20的所有⽤戶[2種⽅式] user_list=Wdtest.query.filter(Wdtest.name.startswith('wa'),Wdtest.age == 20).all() user_list=Wdtest.query.filter(and_(Wdtest.name.startswith('wa'), Wdtest.age == 20)).all() # 非條件查詢查詢名字不等於wade的所有⽤戶[2種⽅式] user_list=Wdtest.query.filter(not_(Wdtest.name == 'wade')).all() user_list=Wdtest.query.filter(Wdtest.name != 'wade').all() # in 條件查詢 user_list=Wdtest.query.filter(Wdtest.id.in_(['97124f50-0208-11ea-a66c-04ea56212bdf', '3'])).all() # 所有⽤戶先按年齡從⼩到⼤, 再按id從⼤到⼩排序, 取前5個 user_list=Wdtest.query.order_by(Wdtest.age,Wdtest.id.desc()).limit(5).all() # 分⻚查詢, 每⻚3個, 查詢第2⻚的資料 pn = Wdtest.query.paginate(2,3) print(pn.pages) print(pn.page) print(pn.items)
有時我們需要將同一類 URL 對映到同一個檢視函數處理,比如:使用同一個檢視函數來顯示不同使用者的個人資訊。
# 路由傳遞引數 @app.route('/user/<id>') def user_info(id): return '%s' % id
路由傳遞的引數預設當做 string 處理
####指定請求方式
在 Flask 中,定義一個路由,預設的請求方式為:
在裝飾器新增請求指定方式:
@app.route('/test', methods=['GET', 'POST']) def test(): return "ok"
flask實現正則匹配步驟:
實現:
匯入轉換器基礎類別
from werkzeug.routing import BaseConverter
自定義轉換器
# 自定義正則轉換器 class RegexConverter(BaseConverter): def __init__(self, url_map, *args): super(RegexConverter, self).__init__(url_map) # 將接受的第1個引數當作匹配規則進行儲存 self.regex = args[0]
新增轉換器到預設的轉換器字典中,並指定轉換器使用時名字為: re
app = Flask(__name__) # 將自定義轉換器新增到轉換器字典中,並指定轉換器使用時名字為: regex app.url_map.converters['regex'] = RegexConverter
使用轉換器去實現自定義匹配規則
當前此處定義的規則是:3位數位
@app.route('/index/<regex("[0-9]{3}"):id>') def user_info(id): return "id 為 %s" % id
自定義轉換器其他函數實現
繼承於自定義轉換器之後,還可以實現 to_python 和 to_url 這兩個函數去對匹配引數做進一步處理:
to_python:
class RegexConverter(BaseConverter): def __init__(self, url_map, *args): super(RegexConverter, self).__init__(url_map) # 將接受的第1個引數當作匹配規則進行儲存 self.regex = args[0] def to_python(self, value): return int(value)
系統自帶轉換器
DEFAULT_CONVERTERS = { 'default': UnicodeConverter, 'string': UnicodeConverter, 'any': AnyConverter, 'path': PathConverter, 'int': IntegerConverter, 'float': FloatConverter, 'uuid': UUIDConverter, }
Settings._init:
# 設定紀錄檔 # LOG_LEVEL = "DEBUG" LOG_LEVEL = "INFO"
紀錄檔記錄級別
FATAL/CRITICAL = 致命的,危險的 ERROR = 錯誤 WARNING = 警告 INFO = 資訊 DEBUG = 偵錯 NOTSET = 沒有設定
application._init:
1、紀錄檔模組基礎設定,如:紀錄檔存放地址、紀錄檔記錄格式、紀錄檔等級
#增加紀錄檔模組 def setup_log(Config): #設定紀錄檔等級 logging.basicConfig(level=Config.LOG_LEVEL) # 建立紀錄檔記錄器,指明紀錄檔儲存的路徑、每個紀錄檔檔案的最大大小、儲存的紀錄檔檔案個數上限 file_log_handler=RotatingFileHandler('log/log',maxBytes=1024 * 1024 * 300, backupCount=10) # 建立紀錄檔記錄的格式 紀錄檔等級 輸入紀錄檔資訊的檔名 行數 紀錄檔資訊 formatter = logging.Formatter('%(asctime)s: %(levelname)s %(filename)s:%(lineno)d %(message)s') # 為剛建立的紀錄檔記錄器設定紀錄檔記錄格式 file_log_handler.setFormatter(formatter) # 為全域性的紀錄檔工具物件(flaskapp使用的)新增紀錄檔記錄器 logging.getLogger().addHandler(file_log_handler)
2、紀錄檔啟動
#紀錄檔啟動 setup_log(Config)
之前我們在config中已經把redis的設定已經寫進去了,所以這裡可以直接創redis連線池供app全域性使用
application._init:
#新增redis連線模組 def connectRedis(Config): pool = redis.ConnectionPool(host=Config.REDIS_HOST, port=Config.REDIS_PORT, password=Config.REDIS_PASSWORD, max_connections=Config.REDIS_POLL) redis_store = redis.Redis(connection_pool=pool) return redis_store
使用範例:
@index_blu.route("/redis",methods=["POST","GET"]) def add_toRedis(): logging.info("come to here") key = request.args.get("key") application.redis_store.set(key , "1233") value=application.redis_store.get( key ) print(value) return "12333"
# rabbitmq設定存取 # 新增使用者名稱和密碼 credentials = pika.PlainCredentials(Config.RABBITUSER, Config.RABBITPASSWORD) # 設定連線引數 parameters = pika.ConnectionParameters(host=Config.RABBITHOST, port=Config.RABBITPORT, credentials=credentials) connection = pika.BlockingConnection(parameters) channel = connection.channel()
使用範例:
@index_blu.route("/rabitmq",methods=["POST","GET"]) def add_rabitmq(): logging.info("come to rabiitmq") application.channel.queue_declare(queue='queuetest2') return "33333"
filerter.requestFilter
這裡只是簡單針對請求路徑非index的進行攔截,如果還有其他攔截條件或者機制,可以繼續在filter這個包下新增
from flask import request import application # 攔截器,每次的請求進來都會做的操作 @application.app.before_request def before_action(): # 獲取當前請求的路由(路徑) a = request.path print(a) u = a.split('/') if len(a)>2: if u[1] == 'index': print('success') else: return "無許可權請求"
攔截器載入進app:
#攔截器載入 requestFilter.before_action
請求物件request,使用前先匯入request模組
from flask import request
Response
檢視函數中可以返回的值
實現一個自定義Response物件步驟
force_typeforce_type(cls,rv,environ=None)
app.response
為你定義的類實現
class JSONResponse(Response): @classmethod def force_type(cls, response, environ=None): ''' 這個方法只有檢視函數返回非字元、非元祖、非Response物件才會呼叫 :param response:是檢視函數的返回值 :param environ: :return: ''' print(response) print(type(response)) if isinstance(response,(list,dict)): #jsonify除了將字典轉換成json物件,還將物件包裝成了一個Response物件 response = jsonify(response) return super(JSONResponse,cls).force_type(response,environ) app.response_class = JSONResponse
捕獲錯誤
errorhandler 裝飾器
引數:
例如統一處理狀態碼為500,404的錯誤給使用者友好的提示:
@app.errorhandler(500) def internal_server_error(e): return '伺服器搬家了哈哈哈' @app.errorhandler(404) def internal_server_error(e): return '瞎請求什麼路徑呢'
例如自定義錯誤413
@app.errorhandler(413) def zero_division_error(e): return '除數不能為0'
異常捕獲
abort 方法
引數:
code – HTTP的錯誤狀態碼
@index_blu.route("/exception",methods=["POST","GET"]) def exception(): logging.info("come to exception") try: print(2) a=3/0 except: abort(413) return "ooooo"
上下文:即語境,語意,在程式中可以理解為在程式碼執行到某個時刻,根據之前程式碼鎖做的操作以及下文即將要執行的邏輯,可以決定在當前時刻下可以使用到的變數,或者可以做的事情。
Flask中有兩種上下文:請求上下文(request context)
和應用上下文(application context)
。
Flask中上下文物件:相當於一個容器,儲存了Flask程式執行過程中的一些資訊。
1.application指的是當你呼叫app = flask(name)建立的這個物件app。 2.request指的是每次http請求發生時,WSGI server(比如gunicorn)呼叫Flask.call()之後,在Flask物件內部建立的Request物件; 3.application表示用於相應WSGI請求的應用本身,request表示沒出http請求; 4.appliacation的生命週期大於request,一個application存活期間,可能發生多次http請求,所以,也就會有多個request;
請求上下文(request context):在Flask中,可以直接在檢視函數中使用request這個獨享進行獲取先關資料,而request就是請求上下文的物件,儲存了當前本次請求的相關資料,請求上線文物件有:request、session
request:封裝了HTTP請求的內容,針對的是http請求。例如:user = request.args.get('user'),獲取的是get請求的引數。
session:用來記錄請求對談中的資訊,針對的是使用者資訊。例如:session['name'] = user.id 科可以記錄使用者資訊。還可以通過session.get('name')獲取使用者資訊。
應用上下文(application context):它不是一直存在的,它只是request context中的一個對app的代理,所謂的local proxy。它的作用主要是幫助request獲取當前的應用,它是伴request而生,隨request而滅的。
應用上下文物件有:current_app,g
current_app:應用程式上下文,用於儲存應用程式中的變數,可以通過current_app.name列印當前app的名稱,也可以在current_app中儲存一些變數,例如:
應用的啟動指令碼是哪個檔案,啟動時指定了哪些引數
載入了哪些組態檔,匯入了哪些設定
連線了哪個資料庫
有哪些可以呼叫的工具類、常數
當前flask應用在哪個機器上,哪個IP上執行,記憶體多大
current_app.name current_app.test_value='value'
g變數:g 作為 flask 程式全域性的一個臨時變數,充當者中間媒介的作用,我們可以通過它傳遞一些資料,g 儲存的是當前請求的全域性變數,不同的請求會有不同的全域性變數,通過不同的thread id區別
g.name='abc'
注意:不同的請求,會有不同的全域性變數
兩者的區別:
請求上下文:儲存了使用者端和伺服器互動的資料
應用上下文:flask 應用程式執行過程中,儲存的一些設定資訊,比如程式名、資料庫連線、應用資訊等
gunicorn作為伺服器,安裝gunicorn
pip3 install gunicorn
啟動
gunicorn -w 3 -b 127.0.0.1:8000 app:app
-w 處理程序數
-b 運⾏主機ip端⼝
dpj.wsgi 項⽬的wsgi
gunicorn常⽤設定
-c CONFIG : CONFIG,設定⽂件的路徑,通過設定⽂件啟動;⽣產環境使⽤; -b ADDRESS : ADDRESS,ip加端⼝,繫結運⾏的主機; -w INT, --workers INT:⽤於處理⼯作程序的數量,為正整數,預設為1; -k STRTING, --worker-class STRTING:要使⽤的⼯作模式,預設為sync非同步,可以下載 eventlet和gevent並指定 --threads INT:處理請求的⼯作執行緒數,使⽤指定數量的執行緒運⾏每個worker。為正整數,預設為1。 --worker-connections INT:最⼤使用者端並行數量,預設情況下這個值為1000。 --backlog int:未決連線的最⼤數量,即等待服務的客戶的數量。預設2048個,⼀般不修改; -p FILE, --pid FILE:設定pid⽂件的⽂件名,如果不設定將不會建立pid⽂件 --access-logfile FILE : 要寫⼊的存取⽇志⽬錄--access-logformat STRING:要寫⼊的存取⽇志格式 --error-logfile FILE, --log-file FILE : 要寫⼊錯誤⽇志的⽂件⽬錄。 --log-level LEVEL : 錯誤⽇志輸出等級。 --limit-request-line INT : HTTP請求頭的⾏數的最⼤⼤⼩,此引數⽤於限制HTTP請求⾏的允 許⼤⼩,預設情況下,這個值為4094。值是0~8190的數位。 --limit-request-fields INT : 限制HTTP請求中請求頭欄位的數量。此欄位⽤於限制請求頭字 段的數量以防⽌DDOS攻擊,預設情況下,這個值為100,這個值不能超過32768 --limit-request-field-size INT : 限制HTTP請求中請求頭的⼤⼩,預設情況下這個值為8190 位元組。值是⼀個整數或者0,當該值為0時,表示將對請求頭⼤⼩不做限制 -t INT, --timeout INT:超過這麼多秒後⼯作將被殺掉,並重新啟動。⼀般設定為30秒; --daemon: 是否以守護行程啟動,預設false; --chdir: 在載入應⽤程式之前切換⽬錄; --graceful-timeout INT:預設情況下,這個值為30,在超時(從接收到重啟訊號開始)之後仍然活著 的⼯作將被強⾏殺死;⼀般使⽤預設; --keep-alive INT:在keep-alive連線上等待請求的秒數,預設情況下值為2。⼀般設定在1~5秒之 間。 --reload:預設為False。此設定⽤於開發,每當應⽤程式發⽣更改時,都會導致⼯作重新啟動。 --spew:列印伺服器執⾏過的每⼀條語句,預設False。此選擇為原⼦性的,即要麼全部列印,要麼全部 不列印; --check-config :顯示現在的設定,預設值為False,即顯示。 -e ENV, --env ENV: 設定環境變數;
到此這篇關於Flask專案搭建及部署(最全教學)的文章就介紹到這了,更多相關Flask專案搭建部署內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45