ORM框架SQLAlchemy與權限管理系統的數據庫設計
SQLAlchemy是Python編程語言下的一款ORM框架,該框架建立在數據庫API之上,使用對象關系映射進行數據庫操作,即:將對象轉換成SQL,然後使用數據API執行SQL並獲取執行結果。
執行流程:
1、使用者通過ORM對象提交命令 2、將命令交給SQLAlchemy Core(Schema/Types SQL Expression Language)轉換成SQL 3、使用 Engine/ConnectionPooling/Dialect 進行數據庫操作 4、匹配使用者事先配置好的egine 5、egine從連接池中取出一個鏈接 6、基於該鏈接通過Dialect調用DB API,將SQL轉交給它去執行
1、關於DB API
SQLAlchemy本身無法操作數據庫,其必須依賴pymsql等第三方插件,Dialect用於和數據API進行交流,根據配置文件的不同調用不同的數據庫API,從而實現對數據庫的操作。
1、MySQL-Python
mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>
2、pymysql
mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]
3、MySQL-Connector
mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname>
4、cx_Oracle
oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...]
更多詳見:http://docs.sqlalchemy.org/en/latest/dialects/index.html
2、創建表操作
在ORM框架下的Alchemy中,類==>表table 對象==>數據行column ;
四張表:業務線,服務,用戶,角色,利用ORM創建出它們,並建立好它們直接的關系
from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column,Integer,String,DateTime,Enum,ForeignKey,UniqueConstraint,ForeignKeyConstraint,Index from sqlalchemy.orm import sessionmaker egine=create_engine(‘mysql+pymysql://[email protected]:3306/db1?charset=utf8‘,max_overflow=5) Base=declarative_base() #創建單表:業務線 class Business(Base): __tablename__=‘business‘ id=Column(Integer,primary_key=True,autoincrement=True) bname=Column(String(32),nullable=False,index=True) #多對一:多個服務可以屬於一個業務線,多個業務線不能包含同一個服務 class Service(Base): __tablename__=‘service‘ id=Column(Integer,primary_key=True,autoincrement=True) sname=Column(String(32),nullable=False,index=True) ip=Column(String(15),nullable=False) port=Column(Integer,nullable=False) business_id=Column(Integer,ForeignKey(‘business.id‘)) __table_args__=( UniqueConstraint(ip,port,name=‘uix_ip_port‘), Index(‘ix_id_sname‘,id,sname) ) #一對一:一種角色只能管理一條業務線,一條業務線只能被一種角色管理 class Role(Base): __tablename__=‘role‘ id=Column(Integer,primary_key=True,autoincrement=True) rname=Column(String(32),nullable=False,index=True) priv=Column(String(64),nullable=False) business_id=Column(Integer,ForeignKey(‘business.id‘),unique=True) #多對多:多個用戶可以是同一個role,多個role可以包含同一個用戶 class Users(Base): __tablename__=‘users‘ id=Column(Integer,primary_key=True,autoincrement=True) uname=Column(String(32),nullable=False,index=True) class Users2Role(Base): __tablename__=‘users2role‘ id=Column(Integer,primary_key=True,autoincrement=True) uid=Column(Integer,ForeignKey(‘users.id‘)) rid=Column(Integer,ForeignKey(‘role.id‘)) __table_args__=( UniqueConstraint(uid,rid,name=‘uix_uid_rid‘), ) def init_db(): Base.metadata.create_all(egine) def drop_db(): Base.metadata.drop_all(egine) if __name__ == ‘__main__‘: init_db()示例代碼
3、對於表的增刪改查
from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column,Integer,String,ForeignKey from sqlalchemy.orm import sessionmaker egine=create_engine(‘mysql+pymysql://[email protected]:3306/db1?charset=utf8‘,max_overflow=5) Base=declarative_base() class Dep(Base): __tablename__=‘dep‘ id=Column(Integer,primary_key=True,autoincrement=True) dname=Column(String(64),nullable=False,index=True) class Emp(Base): __tablename__=‘emp‘ id=Column(Integer,primary_key=True,autoincrement=True) ename=Column(String(32),nullable=False,index=True) dep_id=Column(Integer,ForeignKey(‘dep.id‘)) def init_db(): Base.metadata.create_all(egine) def drop_db(): Base.metadata.drop_all(egine) drop_db() init_db() Session=sessionmaker(bind=egine) session=Session()示例代碼
【增】
有兩種row增加的方式:單行增加session.add( );多行增加session.addall( )
#增 row_obj=Dep(dname=‘銷售‘) #按關鍵字傳參,無需指定id,因其是自增長的 session.add(row_obj) session.add_all([ Dep(dname=‘技術‘), Dep(dname=‘運營‘), Dep(dname=‘人事‘), ]) session.commit()View Code
【刪】
session.query(Dep).filter(Dep.id > 3).delete()
session.commit()
View Code
【改】
#改 session.query(Dep).filter(Dep.id > 0).update({‘dname‘:‘哇哈哈‘}) session.query(Dep).filter(Dep.id>0).update ({‘dname‘:Dep.dname+‘_SB‘},synchronize_session=False) session.query(Dep).filter(Dep.id>0).update ({‘id‘:Dep.id*100},synchronize_session=‘evaluate‘) session.commit()View Code
使用Alchemy 進行增、刪、改的操作時最後都需要進行向數據庫提交數據:session.commit( )
【查】
#查所有,取所有字段 res=session.query(Dep).all() #for row in res:print(row.id,row.dname) #查所有,取指定字段 res=session.query(Dep.dname).order_by(Dep.id).all() #for row in res:print(row.dname) res=session.query(Dep.dname).first() print(res) # (‘哇哈哈_SB‘,) #過濾查 res=session.query(Dep).filter(Dep.id > 1,Dep.id <1000) #逗號分隔,默認為and print([(row.id,row.dname) for row in res])View Code
4、子查詢
個人感覺使用連表操作能很大程度代替子查詢的工作量,而且Alchemy實現起來也很方便!
詳細內容參考海峰老師博客,鏈接:http://www.cnblogs.com/linhaifeng/articles/7560153.html
5、權限管理系統的設計
1. 登陸、註冊、找回密碼
2. 權限管理
3. 角色管理
4. 角色分配權限
5. 動態顯示當前登陸用戶權限菜單
1 from sqlalchemy import create_engine 2 from sqlalchemy.ext.declarative import declarative_base 3 from sqlalchemy import Column,Integer,ForeignKey,CHAR,VARCHAR,UniqueConstraint 4 from sqlalchemy.orm import sessionmaker 5 #建立鏈接 6 engine = create_engine("mysql+pymysql://root:[email protected]:3306/test_db?charset=utf8", max_overflow=5) 7 Base = declarative_base() 8 Session = sessionmaker(bind=engine) 9 session = Session() 10 11 #創建用戶信息表 12 class User(Base): 13 __tablename__ = ‘user‘ 14 uid = Column(Integer,primary_key=True,autoincrement=True) 15 name = Column(CHAR(20),nullable=False) 16 pwd = Column(CHAR(20),nullable=False) 17 roll_id = Column(Integer,ForeignKey(‘roll.rid‘)) 18 #__table_args__的參數必須是元組的形式 19 __table_args__ = ( 20 UniqueConstraint(name,pwd,name=‘uni_np‘), #用戶名和密碼不能重復! 21 ) 22 23 #創建權限表 24 class Authority(Base): 25 __tablename__ =‘authority‘ 26 aid = Column(Integer,primary_key=True,autoincrement=True) 27 auth = Column(VARCHAR(255),nullable=True) 28 29 #創建角色表 30 class Roll(Base): 31 __tablename__ =‘roll‘ 32 rid = Column(Integer,primary_key=True,autoincrement=True) 33 dep = Column(VARCHAR(255),nullable=False) 34 35 #角色權限關系表 36 class Ro_au(Base): 37 __tablename__ =‘ro_au‘ 38 id = Column(Integer,primary_key=True,autoincrement=True) 39 rid = Column(Integer,ForeignKey(‘roll.rid‘)) 40 aid = Column(Integer,ForeignKey(‘authority.aid‘)) 41 42 #創建原始關系表 43 def original_table(): 44 session.add_all([ 45 Roll(dep=‘項目經理‘), 46 Roll(dep=‘技術部‘), 47 Roll(dep=‘運營部‘), 48 Roll(dep=‘人事部‘), 49 Roll(dep=‘後勤部‘), 50 Roll(dep=‘普通員工‘), 51 Authority(auth=‘查看個人信息‘), 52 Authority(auth=‘更改用戶信息‘), 53 Authority(auth=‘刪除用戶‘), 54 Authority(auth=‘設定項目整體方案‘), 55 Authority(auth=‘查看項目進度‘), 56 Authority(auth=‘查看項目經費‘), 57 Authority(auth=‘查看項目計劃‘), 58 Authority(auth=‘項目技術方案‘), 59 Authority(auth=‘項目支出管理‘), 60 Authority(auth=‘項目人事安排‘), 61 Authority(auth=‘項目後勤保障‘), 62 ]) 63 session.commit() 64 session.add_all([ 65 User(name=‘alex‘,pwd=‘3714‘,roll_id=1), 66 User(name=‘egon‘,pwd=‘123456‘,roll_id=2), 67 User(name=‘sl‘,pwd=‘761379545‘,roll_id=2), 68 User(name=‘eric‘,pwd=‘123456‘,roll_id=3), 69 User(name=‘mick‘,pwd=‘123456‘,roll_id=4), 70 User(name=‘john‘,pwd=‘123456‘,roll_id=5), 71 User(name=‘kaka‘,pwd=‘123456‘,roll_id=6), 72 ]) 73 session.add_all([ 74 Ro_au(rid=1,aid=1),Ro_au(rid=1,aid=5),Ro_au(rid=1,aid=6), 75 Ro_au(rid=2, aid=1),Ro_au(rid=2, aid=4),Ro_au(rid=2, aid=8), 76 Ro_au(rid=3, aid=1),Ro_au(rid=3, aid=5),Ro_au(rid=3, aid=6),Ro_au(rid=3, aid=7), 77 Ro_au(rid=4, aid=1),Ro_au(rid=4, aid=2),Ro_au(rid=4, aid=3), 78 Ro_au(rid=5, aid=1),Ro_au(rid=5, aid=9),Ro_au(rid=5, aid=11), 79 Ro_au(rid=6, aid=1), 80 ]) 81 session.commit() 82 83 #創建數據庫所有表 84 def creat_db(): 85 Base.metadata.create_all(engine) 86 87 #刪除數據庫所用表 88 def drop_db(): 89 Base.metadata.drop_all(engine) 90 91 #顯示個人權限 92 def show_auth(user_name): 93 user_roll_id = session.query(User.roll_id).filter(User.name == user_name).subquery() 94 user_dep_list = session.query(Roll.dep).filter(Roll.rid == user_roll_id).all() 95 for row in user_dep_list: 96 user_dep = row[0] 97 print(‘您當前所屬部門名稱:‘, user_dep) 98 print(‘\33[33m您具有的權限如下:\33[37m‘) 99 auth_list = session.query(Authority.auth).join(Ro_au).filter(Ro_au.rid == user_roll_id).all() 100 count = 1 101 for auth in auth_list: 102 print(count, auth[0]) 103 count += 1 104 105 #顯示所有部門信息 106 def show_department(): 107 print(‘公司現有部門如下:‘) 108 dep_list = session.query(Roll).all() 109 for dep in dep_list: 110 print(dep[0],dep[1]) 111 112 113 def login(): 114 while True: 115 user_name = input(‘請輸入用戶名【返回B】:\n>>>‘).strip() 116 if user_name.lower() == ‘b‘: 117 break 118 user_pwd = input(‘請輸入用戶密碼【返回B】:\n>>>‘).strip() 119 if user_pwd.lower() == ‘b‘: 120 break 121 user_list = session.query(User.name,User.pwd).all() 122 123 if (user_name,user_pwd) in user_list: 124 print(‘登陸成功!‘) 125 choice = input(‘【1、進入個人權限界面】‘ 126 ‘\n【2、查看公司具有的所有部門】‘ 127 ‘\n【B、返回主界面】‘ 128 ‘\n>>>‘).strip() 129 if choice == ‘1‘: 130 show_auth(user_name) 131 continue 132 if choice == ‘2‘: 133 show_department() 134 continue 135 if choice.lower() == ‘b‘: 136 break 137 else: 138 print(‘用戶名或者密碼錯誤!‘) 139 continue 140 141 #用戶註冊 142 def register(): 143 while True: 144 user_name = input(‘請輸入用戶名【返回B】:\n>>>‘).strip() 145 if not user_name:continue 146 if user_name.lower() == ‘b‘: 147 break 148 name_list = session.query(User.name).all() 149 if (user_name,) in name_list: 150 print(‘該用戶名已經存在!‘) 151 break 152 else: 153 user_pwd = input(‘請輸入用戶密碼:\n>>>‘).strip() 154 if not user_pwd:continue 155 dep_list = session.query(Roll.rid,Roll.dep).all() 156 for row in dep_list: 157 print(row.rid,row.dep) 158 user_roll = input(‘請輸入所屬部門序號:\n>>>‘).strip() 159 if not user_roll: 160 print(‘部門序號不能為空,請重新開始!‘) 161 continue 162 if user_roll.isdigit(): 163 session.add(User(name=user_name,pwd=user_pwd,roll_id=int(user_roll))) #寫入數據庫 164 session.commit() 165 print(‘新的員工信息已經註冊成功!‘) 166 break 167 else: 168 print(‘您選擇的部門有誤,請重新選擇!‘) 169 170 #找回密碼 171 def find_pwd(): 172 while True: 173 user_name =input(‘請輸入用戶名【返回B】:‘).strip() 174 if not user_name:continue 175 if user_name.lower() == ‘b‘: 176 break 177 name_list =session.query(User.name).all() 178 if (user_name,) in name_list: 179 pwd_list =session.query(User.pwd).filter(User.name==user_name).all() 180 print(‘您的密碼為:‘) 181 for pwd in pwd_list: 182 print(pwd[0]) 183 else: 184 print(‘您輸入的用戶名不存在!‘) 185 186 if __name__ == ‘__main__‘: 187 while True: 188 creat_tab_choice = input(‘是否要在數據庫中創建原始關系表?第一次請選擇是!‘ 189 ‘**此操作會刪除已添加的數據!**【是Y否N】:\n>>>‘).strip() 190 if creat_tab_choice.lower() == ‘y‘: 191 drop_db() 192 creat_db() 193 original_table() 194 print(‘基本權限管理原始表已創建!‘) 195 elif creat_tab_choice.lower() == ‘n‘: 196 pass 197 else: 198 print(‘您的操作有誤,請重新選擇!‘) 199 continue 200 while True: 201 print(‘歡迎進入權限管理系統!‘.center(21, ‘*‘)) 202 choice = input(‘登錄L\t註冊R\t找回密碼F\t退出Q:\n>>>‘).strip() 203 if choice.lower() == ‘q‘: 204 print(‘成功退出權限管理系統,歡迎您再次使用!‘) 205 break 206 elif choice.lower() == ‘l‘: 207 login() 208 elif choice.lower() == ‘r‘: 209 register() 210 elif choice.lower() == ‘f‘: 211 find_pwd() 212 else: 213 print(‘您輸入的指令有誤,請重新選擇!‘) 214 continue 215 break
數據庫中的邏輯結構圖如下:
通過該模塊內容的學習,對ORM有了深刻的認識,通過Alchemy語句映射SQL語句來達到我們操作數據庫的目的!
ORM框架SQLAlchemy與權限管理系統的數據庫設計