剛接觸Flask是源於想整合兩個接口服務到一塊裏面,以前開發接口用的是Python spyne並把它集成在Django裏面,感受只是作接口服務沒必集也集成到Django框架裏,不夠靈活。javascript
無心中在網上搜索到Python的Flask框架,網友們使用Flask 設計 RESTful API。今天開始認識Flaskcss
Flask官網上這樣介紹:html
「微」 (「Micro」) 並非意味着把整個 Web 應用放入到一個 Python 文件,儘管確實能夠這麼作。固然「微」 (「Micro」) 也不是意味 Flask 的功能上是不足的。微框架中的 「微」 (「Micro」) 是指 Flask 旨在保持代碼簡潔且易於擴展。前端
易於擴展,靈活選擇模板文件jinja,數據引擎flask-SQLALchemy,表單驗證flask-wtf各種擴展,大多以「flask-」打頭的,添加到應用中實現。使用Flask給個人感覺就是,不斷的下載擴展,添加到virtualenv虛擬開發環境中。java
Python中有一個神器Virtualenv虛擬環境,有了它咱們再也不須要考慮Python版本的差別,不一樣版本的Python2.x或者3.x它們能夠相互獨立,互不影響,不用每次由於版本的不一樣去切換系統的環境變量,大大節省開發的時間成本;python
這符合軟件解耦設計思想,不一樣的應用可使用不一樣的套件版本,彼此互相不受影響。mysql
pip install virtualenvjquery
virtualenv安裝目錄下,cmd到命令行,這裏我建立python2.7的虛擬環境git
virtualenv.exe --python=「C:\Program Files\Python27\python.exe」 "D:\PythonEnv\p2vir"github
--p 或者--python 指定python解析器(Python.exe文件路徑)
p2vir 建立的虛擬環境目錄名稱
(1)下載須要的擴展包,解壓到相應的目錄下,例如我安裝jinja模板擴展的路徑E:\軟件\jinja-master
(2)進入python的虛擬環境:輸入 D:\PythonEnv\p2vir\Scripts\activate.bat
(3)安裝jinja命令:python setup.py install
balabalabala....
Flask很是靈活,沒有絕對的目錄結構,依據我的習慣能夠隨意設計,網上比較場景有兩類,一種是以功能劃分和應用劃分。
項目project下,由models、routes、templates、services,分別用來放數據庫模型、路由文件、模板文件和工具。
project/ __init__.py models/ __init__.py base.py users.py posts.py ... routes/ __init__.py home.py account.py dashboard.py ... templates/ base.html post.html ... services/ __init__.py google.py mail.py ...
project項目下,有個項目初始化文件__init__.py,數據庫文件db.py,兩個應用auth和blog分別劃分到不一樣的目錄下,每一個目錄下都有單獨的route、models和templates,目錄結果比較清晰明瞭
project/ __init__.py db.py auth/ __init__.py route.py models.py templates/ blog/ __init__.py route.py models.py templates/ ...
綜合比較這兩種劃分方式,我用的是後者,應用劃分。我使用的是Pycharm IDE,如下是個人Flask項目目錄結構
模板文件統一放到粉色的模板文件目錄 templates,templates目錄是在Pycharm建立Flask項目,勾選虛擬環境的時候自動建立的。
jinja2是Python的一套模板引擎,靈感來自Django的模板並進行了擴展。
開始使用jinja2,一塊兒來挖坑+填坑
模板文件layout.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>{% block title %}{% endblock %}</title> 6 <link rel="stylesheet" href="static/layui/css/layui.css" media="all"> 7 <script type="text/javascript" src="static/layui/layui.js"></script> 8 <script type="text/javascript" src="static/js/jquery-3.1.1.min.js"></script> 9 {% block customstyle %} {% endblock %} 10 {% block customscript %} {% endblock %} 11 </head> 12 <body> 13 {% block conent %}{% endblock %} 14 </body> 15 </html>
實現頁面warehouse.html
1 {% extends 'layout.html' %} 2 {% block title %}倉庫管理{% endblock %} 3 {% block customstyle %} 4 <style> 5 body { 6 overflow-y: scroll; 7 } 8 </style> 9 {% endblock %} 10 {% block customscript %} 11 <script> 12 function renderForm() { 13 layui.use('form', function () { 14 var form = layui.form; 15 form.render(); 16 }); 17 } 18 </script> 19 {% endblock %} 20 {% block conent %} 21 <div id="content"> 22 <div class="layui-inline"> 23 </div> 24 <div class="layui-inline" style="width:1200px;height:400px;padding-left:10px" > 25 <table id="warehouse" lay-filter="test"></table> 26 </div> 27 </div> 28 {% endblock %}
layui官網下載前端框架壓縮包,解壓縮到相應目錄下,拷貝layui目錄放到項目裏面,實現頁面添加引用,就能夠開始用layui咯。
我把layui放在static目錄下:
python使用pymysql做爲數據庫引擎鏈接和操做數據庫,Flask-SQLALchemy是一套ORM(Object Relationship Mapping模型關係映射),
面向對象的思想,一切事物皆是對象,Flask-SQLALchemy ORM可讓咱們操做數據庫跟操做對象是同樣的,很是方便。一個表就抽象成一個類,一條數據就抽象成該類的一個對象。
config.py文件,記錄項目相關配置信息,包括指明模板文件的路徑、靜態文件的路徑、數據庫URI(數據庫mysql、數據庫引擎pymysql,域名地址,數據庫,登陸用戶,登陸密碼,端口號)、數據庫超時、鏈接池等屬性
1 # -*- coding: utf-8 -*- 2 import os 3 4 BASE_DIR = os.getcwd() # 項目的絕對路徑 5 6 TEMPLATES_DIR = os.path.join(BASE_DIR, 'templates') # 模板文件的路徑 7 8 STATICFILES_DIR = os.path.join(BASE_DIR, 'static') # 靜態文件的路徑 9 10 DIALECT = 'mysql' 11 DRIVER = 'pymysql' 12 USERNAME = 'root' 13 PASSWORD = 'xxxx' 14 HOST = 'xx.xx.xx.xx' 15 PORT = '3306' 16 DATABASE = 'xxx' 17 18 # 數據庫URI 19 SQLALCHEMY_DATABASE_URI = '{}+{}://{}:{}@{}:{}/{}?charset=utf8'.format( 20 DIALECT, DRIVER, USERNAME, PASSWORD, HOST, PORT, DATABASE 21 ) 22 23 SQLALCHEMY_TRACK_MODIFICATIONS = True # 查詢跟蹤,不太須要,False,不佔用額外的內存 24 25 SQLALCHEMY_COMMIT_TEARDOWN = True 26 27 SQLALCHEMY_POOL_SIZE = 100 # 數據庫鏈接池大小 28 29 SQLALCHEMY_POOL_TIMEOUT = 30 # 鏈接池的鏈接超時時間
__init__.py文件,初始化Flask對象並返回。
1 # -*- coding: utf-8 -*- 2 from flask import Flask 3 from flask_sqlalchemy import SQLAlchemy 4 from config import SQLALCHEMY_DATABASE_URI, SQLALCHEMY_TRACK_MODIFICATIONS, SQLALCHEMY_COMMIT_TEARDOWN, \ 5 SQLALCHEMY_POOL_SIZE, SQLALCHEMY_POOL_TIMEOUT 6 7 db = SQLAlchemy() # 初始化SQLAlchemy 8 9 10 def create_app(): 11 """建立app的方法""" 12 app = Flask(__name__) # 生成Flask對象 13 app.config['SQLALCHEMY_DATABASE_URI'] = SQLALCHEMY_DATABASE_URI # 配置 app的URI 14 app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = SQLALCHEMY_TRACK_MODIFICATIONS 15 app.config['SQLALCHEMY_COMMIT_TEARDOWN'] = SQLALCHEMY_COMMIT_TEARDOWN 16 app.config['SQLALCHEMY_POOL_SIZE'] = SQLALCHEMY_POOL_SIZE 17 app.config['SQLALCHEMY_POOL_TIMEOUT'] = SQLALCHEMY_POOL_TIMEOUT 18 19 db.init_app(app=app) 20 21 # 在這裏還可設置好配置後,初始化其餘的模塊 22 23 return app # 返回Flask對象app
models.py文件,數據庫模型,使用Flask-SQLALchemy進行ORM映射,使得咱們能夠想操做對象同樣操做數據庫的增、刪、改、查。
1 # -*- coding: utf-8 -*- 2 from flask import Flask 3 from flask_sqlalchemy import SQLAlchemy 4 from iMock import create_app 5 from flask_script import Manager 6 import datetime 7 8 # 建立Flask對象 9 app = create_app() 10 11 # 獲取SQLAlchemy實例對象,接下來就可使用對象調用數據 12 db = SQLAlchemy(app) 13 14 15 class SFErpOrder(db.Model): 16 __tablename__ = 't_sf_erpOrder' 17 id = db.Column(db.Integer, primary_key=True) 18 skuNo = db.Column('skuNo', db.String(200)) 19 qty = db.Column(db.Integer) 20 erpOrder = db.Column('erpOrder', db.String(100)) 21 warehouseCode = db.Column('warehouseCode', db.String(100)) 22 serialNumber = db.Column('serialNumber', db.Text) 23 receiptId = db.Column('receiptId', db.String(100)) 24 create_time = db.Column(db.DateTime, default=datetime.datetime.now()) 25 modify_time = db.Column(db.DateTime, default=datetime.datetime.now()) 26 27 def to_json(self): 28 dict = self.__dict__ 29 if "_sa_instance_state" in dict: 30 del dict["_sa_instance_state"] 31 return dict 32 33 def __repr__(self): 34 return '<t_sf_erpOrder %r> ' % self.id 35 36 37 class SFOutErpOrder(db.Model): 38 __tablename__ = 't_sf_outErpOrder' 39 id = db.Column(db.Integer, primary_key=True) 40 skuNo = db.Column('skuNo', db.String(200)) 41 fqlOrder = db.Column('fqlOrder', db.String(100)) # 分期樂訂單O20170831XXXXXXX 42 warehouseCode = db.Column('warehouseCode', db.String(100)) 43 outIMEI = db.Column('outIMEI', db.Text) 44 itemQuantity = db.Column(db.Integer) 45 shipMentId = db.Column('shipMentId', db.String(100)) 46 create_time = db.Column(db.DateTime, default=datetime.datetime.now()) 47 modify_time = db.Column(db.DateTime, default=datetime.datetime.now()) 48 49 def __repr__(self): 50 return '<t_sf_outErpOrder %r> ' % self.id 51 52 53 manager = Manager(app) 54 55 if __name__ == '__main__': 56 db.create_all() # 建立數據表 57 manager.run()
Flask-SQLALchemy經常使用數據類型:
Flask-SQLALchemy可選參數:
Flask-SQLALchemy數據表主外鍵關係:
1對多關係
1 class Person(db.Model): 2 id = db.Column(db.Integer, primary_key=True) 3 name = db.Column(db.String(50), nullable=False) 4 addresses = db.relationship('Address', backref='person', lazy=True) 5 6 class Address(db.Model): 7 id = db.Column(db.Integer, primary_key=True) 8 email = db.Column(db.String(120), nullable=False) 9 person_id = db.Column(db.Integer, db.ForeignKey('person.id'), 10 nullable=False)
多對多關係
1 tags = db.Table('tags', 2 db.Column('tag_id', db.Integer, db.ForeignKey('tag.id'), primary_key=True), 3 db.Column('page_id', db.Integer, db.ForeignKey('page.id'), primary_key=True) 4 ) 5 6 class Page(db.Model): 7 id = db.Column(db.Integer, primary_key=True) 8 tags = db.relationship('Tag', secondary=tags, lazy='subquery', 9 backref=db.backref('pages', lazy=True)) 10 11 class Tag(db.Model): 12 id = db.Column(db.Integer, primary_key=True)
Flask-SQLALchemy數據庫操做:
操做數據庫,根據查詢條件像 sql where同樣實現條件查詢。更多操做
from .models import * try: sfErpOrder = SFErpOrder().query.filter_by(erpOrder=ErpOrder).first()
# total_count = SFErpOrder.query.filter_by(**filter_dict).count() # filter_by支持多條件查詢 **filter_dict字典參數
except Exception as err:
print traceback.print_exc()
Flask-Migrate是Flask的一個擴展,底層使用的是Alembic,主要用來處理Flask應用關於SQLAlchemy數據庫變動的遷移。更多
相關命令:
初始化數據庫,在工程中新建migrations目錄,在數據庫中生成一個alembic_version表,記錄數據庫遷移版本信息version_num
python manage.py db init
執行如下命令,生成數據庫遷移腳本文件,保存在versions目錄下面
python manage.py db migrate
官網有這麼一句話:
The migration script needs to be reviewed and edited, as Alembic currently does not detect every change you make to your models.
In particular, Alembic is currently unable to detect table name changes, column name changes, or anonymously named constraints.
意思是flask-migrate底層的Alembic不可以偵測到所有對於模型的改動,包括數據表名稱變動、字段名稱變動或者匿名命名約束的變化等。這個時候
咱們能夠手動修改migrate生成的版本文件
1 def upgrade(): # 升級方法 2 # 舉個例子:這裏修改數據表t_sf_erpOrder字段名skuNoo爲skuNo,而且變動字符串長度爲200字節 3 op.alter_column('t_sf_erpOrder', 'skuNoo', new_column_name='skuNo',existing_type=mysql.VARCHAR(length=200)) 4 5 def downgrade(): # 降級方法 6 op.create_table('t_sf_erpOrder', 7 sa.Column('id', mysql.INTEGER(display_width=11), autoincrement=True, nullable=False), 8 sa.Column('skuNoo', mysql.VARCHAR(length=100), nullable=True),
最後把數據庫變動應用到數據庫,使得改動生效。更多操做
python manage.py db upgrade
Flask-Script是Flask的一個擴展,使得Flask能夠執行外部的腳本,包括運行開發服務器,自定義的Python shell腳本,數據庫操做腳本,定時cronbjobs任務和其餘命令行腳本。更多
Flask-Script和Flask-migrate的應用實例:
這個是個人manage.py項目啓動文件
1 # -*- coding: utf-8 -*- 2 from flask_script import Manager, Server 3 from flask_migrate import MigrateCommand, Migrate 4 from flask_sqlalchemy import SQLAlchemy 5 from iMock import create_app 6 from iMock.api import api 7 from iMock.warehouse import warehouse 8 """ 9 注意 10 11 在這裏必定要嚴格在遵照Python導入包的編寫順序 12 13 Python Build In 內構包 14 Python 第三方庫 15 用戶自定義模塊 16 """ 17 18 19 app = create_app() # 建立app 20 app.register_blueprint(api, url_prefix='/imock') # 註冊藍圖 21 app.register_blueprint(warehouse, url_prefix='/warehouse') # 註冊藍圖 22 23 manager = Manager(app) # 經過app建立manager對象 24 db = SQLAlchemy(app) 25 migrate = Migrate(app, db) 26 27 manager.add_command("runserver", Server(use_debugger=True)) # 添加到命令行 28 manager.add_command("db", MigrateCommand) # 添加到命令行 29 30 31 if __name__ == '__main__': 32 manager.run() # 運行服務器
在Pycharm中,設置下啓動配置啓動參數,Run->Edit Configuration...->Configuration的Parameters設置爲「runserver --thread」 ,參數的意識「開啓多線程模式」,避免頻繁訪問緩慢卡頓。
直接右鍵執行manage.py啓動腳本,看到下面的終端日誌,說明服務器啓動成功,默認端口號5000,能夠開始訪問了
Python Flask框架已經基本搭建完畢,期間涉及到Flask框架特性和原理、項目結構,Flask的配置文件、jinja2模板、Flask-SQLAlchemy,Pymysql,Flask-script,Flask-Migrate,Alembic,啓動文件相關知識;
目前算是入了Flask的門,接下來就要在平時的實踐中不斷去摸索和學習框架的相關東西,Flask的各種擴展,使得Flask更好地應用到個人工做當中。
轉載&&參考:
Python Flask 官網 http://www.pythondoc.com/flask/index.html
Python Flask 開發環境virtualenv搭建 https://blog.csdn.net/doago/article/details/50488586
Virtualenv用戶操做指南 https://virtualenv.pypa.io/en/latest/reference/
Python Flask項目結構 https://lepture.com/en/2018/structure-of-a-flask-project
前端框架Layui https://www.layui.com/
Alembic http://www.javashuo.com/article/p-wctwvdhz-md.html
做者的寄語:
天天進步一點點,慢慢成爲更好的本身。