基於Flask實現後臺權限管理系統 - Flask
1. Flask
1.1. 簡介
Flask是使用Python編寫的輕量級Web應用框架,其WSGI工具箱采用Werkzeug,模板引擎則使用Jinja2。Flask使用BSD授權,Flask也被稱為“microframework”,因為它使用簡單的核心,用extension增加其他功能,用戶可以隨意地進行組合,滿足自己的要求。
一段最簡單的Flask代碼如下:
1 from flask import Flask 2 3 app = Flask(__name__) 4 5 6 7 @app.route(‘/‘) 8 9def hello_world(): 10 11 return ‘Hello World!‘ 12 13 14 15 if __name__ == ‘__main__‘: 16 17 app.run()
那麽,這段代碼做了什麽?
首先,我們導入了Flask類。這個類的實例將會是我們的WSGI應用程序。
接下來,我們創建一個該類的實例,第一個參數是應用模塊或者包的名稱。 如果你使用單一的模塊(如本例),你應該使用__name__,因為模塊的名稱將會因其作為單獨應用啟動還是作為模塊導入而有不同( 也即是 ‘__main__‘ 或實際的導入名)。這是必須的,這樣
然後,我們使用route()裝飾器告訴Flask什麽樣的URL能觸發我們的函數。
這個函數的名字也在生成URL時被特定的函數采用,這個函數返回我們想要顯示在用戶瀏覽器中的信息。
最後我們用run()函數來讓應用運行在本地服務器上。 其中if __name__ == ‘__main__‘: 確保服務器只會在該腳本被Python解釋器直接執行的時候才會運行,而不是作為模塊導入的時候。
1.2. Flask-SQLAlchemy
Flask-SQLAlchemy是對Flask的一個插件,是Flask對SQLAlchemy
常見情況下對於只有一個Flask應用,所需要做的事情就是創建Flask應用,選擇加載配置,接著創建SQLAlchemy對象時候,把Flask應用傳遞給它作為參數。
一旦創建,這個對象就包含 sqlalchemy 和 sqlalchemy.orm 中的所有函數和助手。此外它還提供一個名為 Model 的類,用於作為聲明模型時的 delarative 基類:
1 class User(db.Model): 2 3 id = db.Column(db.Integer, primary_key=True) 4 5 username = db.Column(db.String(80), unique=True) 6 7 8 9 def __init__(self, username, email): 10 11 self.username = username 12 13 14 15 def __repr__(self): 16 17 return‘<User %r>‘ % self.username
1.2.1. 一對多關系
以資源類型和資源舉例說明,它們之間關系是一對多關系,一個資源類型下可以有多個資源,而資源只屬於一種類型,如果前面介紹,資源只能是菜單類型或功能類型的一種。
1 class ResourceType(db.Model): 2 3 __tablename__ = ‘SYRESOURCETYPE‘ 4 5 ID = db.Column(db.String(36), primary_key=True) 6 7 CREATEDATETIME = db.Column(db.DateTime, index=True, default=datetime.now) 8 9 UPDATEDATETIME = db.Column(db.DateTime, index=True, default=datetime.now) 10 11 NAME = db.Column(db.String(100)) 12 13 DESCRIPTION = db.Column(db.String(200)) 14 15 resources = db.relationship(‘Resource‘, backref=‘type‘, lazy=‘dynamic‘)
1 class Resource(db.Model): 2 3 __tablename__ = ‘SYRESOURCE‘ 4 5 ID = db.Column(db.String(36), primary_key=True) 6 7 # 省略部分內容 8 9 NAME = db.Column(db.String(100)) 10 11 SYRESOURCETYPE_ID = db.Column(db.String, db.ForeignKey(‘SYRESOURCETYPE.ID‘))
ResourceType類通過relationship關聯到Resource類,給自己定義了resources集合屬性,代表本類型下的所有資源。db.relationship關聯到Resource類,通過backref動態地給Resource類增加了type屬性,代表Resource所屬的資源類型。
1.2.2. 多對多關系
以用戶和角色為例,它們之間的關系是多對多關系,一個用戶可以有多個角色,一個角色也可以被多個用戶所用。
user_role_table = db.Table(‘SYUSER_SYROLE‘, db.Model.metadata
, db.Column(‘SYUSER_ID‘, db.String, db.ForeignKey(‘SYUSER.ID‘))
, db.Column(‘SYROLE_ID‘, db.String, db.ForeignKey(‘SYROLE.ID‘)))
1 class User(db.Model): 2 3 __tablename__ = ‘SYUSER‘ 4 5 ID = db.Column(db.String(36), primary_key=True) 6 7 LOGINNAME = db.Column(db.String(100), unique=True, index=True) 8 9 PWD = db.Column(db.String(100)) 10 11 NAME = db.Column(db.String(100)) 12 13 14 15 roles = db.relationship(‘Role‘,secondary=user_role_table, 16 17 backref=db.backref(‘users‘, lazy=‘dynamic‘))
1 class Role(db.Model): 2 3 __tablename__ = ‘SYROLE‘ 4 5 ID = db.Column(db.Integer, primary_key=True) 6 7 NAME = db.Column(db.String(100))
User類中通過db.relationship定義了和Role類之間的關系,它們之間連接的橋梁就是user_role_table,user_role_table定義了兩張關聯表之間主鍵的對應關系。User對象含有roles集合屬性,代表角色的集合,而通過backref動態地給Role對象增加了users屬性,代表本角色所從屬的用戶有哪些。
註:ORM將對象映射到數據表,對象之間的關系映射到表之間的關系,通過操作對象及其之間的關系即可以操作數據庫表,非常方便,不需要寫SQL語句。
1.3. 集成Python Shell
Flask-Script的shell命令可以導入指定的對象,這樣就可以在控制臺操作Python對象,譬如用戶對象、資源對象等等,即時測試對象的屬性和方便,使用起來比較方便。
1 ###########################manager.py#################### 2 3 from app.models import User, Role, Resource, ResourceType, Organization 4 5 from flask_script import Manager, Shell 6 7 from flask_migrate import Migrate, MigrateCommand 8 9 10 11 def make_shell_context(): 12 13 return dict(app=app, db=db, User=User, Role=Role, Resource=Resource, 14 15 ResourceType=ResourceType, Organization=Organization) 16 17 18 19 manager.add_command("shell", Shell(make_context=make_shell_context)) 20 21 manager.add_command(‘db‘, MigrateCommand) 22 23 24 25 @manager.command 26 27 def myprint(): 28 29 print ‘hello world‘
代碼使用flask_script下的Manager模塊,通過add_command方法將一些對象註冊到shell上下文中。註冊的方法有兩種:
1)add_command。直接調用Manager模塊下的add_command方法;
> python manager.py shell
>>> db
<SQLAlchemy engine=‘mysql://root:@127.0.0.1/authbase?charset=utf8‘>
>>> app
<Flask ‘app‘>
>>> User.query.all()
[<User u‘\u8d85\u7ea7\u7ba1\u7406\u5458‘>
, <User u‘\u7ba1\u7406\u5458‘>
]
>>>
2)裝飾器方式。使用manager.command裝飾器,裝飾的方法名稱就會成為shell環境中的一條命令。
python manager.py myprint
hello world
1.4. 藍圖
藍圖實現了應用的模塊化,使用藍圖使得應用層次更加清楚,開發者可以更容易地開發和維護項目。藍圖通常作用於相同的URL前綴,譬如/admin/user, /admin/resource等等,將一類相同的功能組合到一起,如果URL前綴發生變化,只需要修改藍圖即可。
舉例說明,通常網站分為用戶網站部分和管理後臺部分,如博客類網站,管理後臺可以編輯文章等操作,編輯後的文章會在用戶網站部分顯示,其它用戶可以閱讀、評論等,同時,管理後臺可以評論進行管理等等。按照模塊劃分:
Blog -------|
| 前臺網站
------------|app/blog/:id
------------|app/blog/:id/comment/:id
| 管理後臺
|admin/user/:id
|admin/role/:id
|admin/siteinfo
上述Blog將網站分為兩個部分:前臺網站和管理後臺,如果按照藍圖實現,即將應用劃分為兩個藍圖。
1 from flask import Blueprint 2 3 app = Blueprint(‘app‘, __name__, url_prefix=‘/app‘) 4 5 admin = Blueprint(‘admin‘, __name__, url_prefix=‘/admin‘) 6 7 8 9 @app.route(‘/blog/:id‘, methods=[‘POST‘]) 10 11 defapp_blog(): 12 13 #查詢指定編號博客賦值給blog對象 14 15 returnrender_template(blog/index.html‘, blog=blog) 16 17 18 19 @admin.route(‘/role/:id‘, methods=[‘POST‘]) 20 21 defadmin_role(): 22 23 #查詢指定編號角色賦值給role對象 24 25 return render_template(role/index.html‘, role=role)
基於Flask實現後臺權限管理系統 - Flask