標籤:
因為買了本機器學習的書是python的,所以學習了一下python,就用python做了一個簡單的web開發的mvc小架構。整個架構分為實體層,資料訪問層,業務基類層,Web請求轉寄層,控制層和視圖層。當然也包括一些輔助性工具類。下面一一介紹,希望對跟我一樣初學python的有點協助:
1)實體層
由實體基類和使用者實體類組成。實體類可以由資料庫自動產生,提供了一個DbTools,可以自動建置規則的實體。下面是實體基類:
import threading#使用者錯誤類,用於拋出自訂的異常class CustomError(RuntimeError): def __init__(self,args): self.args=args#實體的基類. class EntityB: def __init__(self): self.CurrFields=[] #根據屬性名稱擷取屬性值 def GetValueByName(self,FieldName): if hasattr(self,FieldName): return getattr(self,FieldName) return None #根據屬性名稱設定屬性值 def SetValueByName(self,FieldName,Value): if hasattr(self,FieldName): return setattr(self,FieldName,Value) #定義了該屬性,對象可枚舉. def __getitem__(self,key): if type(key)==type(‘abc‘): return self.GetValueByName(key) if type(key)==type(1): theFld = self.CurrFields[key] return self.GetValueByName(theFld) return None #設定屬性值,key可以是索引,也可以是屬性名稱. def __setitem__(self,key,value): if type(key)==type(‘abc‘): self.SetValueByName(key,value) if type(key)==type(1): theFld = self.CurrFields[key] self.SetValueByName(theFld,value) #擷取實體的表名. def GetTableName(self): theType = type(self) if hasattr(theType,‘TableName‘): return getattr(theType,‘TableName‘) return ‘‘ #擷取關鍵字段名 def GetKeyField(self): theType = type(self) if hasattr(theType,‘KeyField‘): return getattr(theType,‘KeyField‘) return ‘‘ #擷取欄位名集合 def GetFields(self): theType = type(self) if hasattr(theType,‘Fields‘): return getattr(theType,‘Fields‘) return [] InsertCondition = threading.Condition() InsertLockSign = False DeleteCondition = threading.Condition() DeleteLockSign = False UpdateAllCondition = threading.Condition() UpdateAllLockSign = False InsertSqlName=‘__InsertSql‘ UpdateAllSqlName=‘__UpdateSql‘ DelByPKSqlName=‘__DelByPKSql‘ DefaultSelectSQL=‘__DefaultSelectSql‘ #根據屬性名稱擷取類型的屬性值。 def _GetClassValue(self,AttrName): theSelfType = type(self) theValue =‘‘ if hasattr(theSelfType,AttrName): theValue=getattr(theSelfType,AttrName) return theValue #根據屬性名稱設定類型的屬性值. def _SetClassValue(self,AttrName,value): theSelfType = type(self) theValue =‘‘ if hasattr(theSelfType,AttrName): setattr(theSelfType,AttrName,value) #擷取欄位參數 def GetFieldParams(self): return self._GetClassValue(‘FieldParams‘) #擷取插入的SQL def GetInsertSQL(self): theSQL =self._GetClassValue(EntityB.InsertSqlName) if (theSQL==None or theSQL==‘‘): EntityB.InsertCondition.acquire() try: if EntityB.InsertLockSign: EntityB.InsertCondition.wait() InsertLockSign = True theSQL =self._GetClassValue(EntityB.InsertSqlName) if (theSQL==None or theSQL==‘‘): theTableName=self.GetTableName() theFields=self.GetFields() if theTableName==‘‘ or theFields==[]: raise CustomError(‘表名或欄位為空白!‘) theSQL=‘INSERT INTO ‘+ theTableName theFlds=‘‘ theVals=‘‘ theFldParams = self.GetFieldParams() for theF in theFields: if theFlds==‘‘: theFlds += theF theVals += theFldParams[theF][‘DSFmt‘] else: theFlds += ‘,‘+theF theVals +=‘,‘+theFldParams[theF][‘DSFmt‘] theSQL+=‘(‘+theFlds+‘) values(‘+theVals+‘)‘ self._SetClassValue(EntityB.InsertSqlName,theSQL) return theSQL finally: InsertLockSign=False EntityB.InsertCondition.notify() EntityB.InsertCondition.release() else: return theSQL #擷取根據主鍵刪除SQL def GetDelByPKSQL(self): theSQL =self._GetClassValue(EntityB.DelByPKSqlName) if (theSQL==None or theSQL==‘‘): EntityB.DeleteCondition.acquire() try: if EntityB.DeleteLockSign: EntityB.DeleteCondition.wait() DeleteLockSign = True theSQL =self._GetClassValue(EntityB.DelByPKSqlName) if (theSQL==None or theSQL==‘‘): theTableName=self.GetTableName() theKeyField=self.GetKeyField() if theTableName==‘‘ or theKeyField==‘‘: raise CustomError(‘表名或主鍵為空白!‘) theFldParams = self.GetFieldParams() theSQL=‘DELETE FROM ‘+ theTableName+‘ WHERE ‘+theKeyField+‘=‘+theFldParams[theKeyField][‘DSFmt‘] self._SetClassValue(EntityB.DelByPKSqlName,theSQL) return theSQL finally: DeleteLockSign=False EntityB.DeleteCondition.notify() EntityB.DeleteCondition.release() else: return theSQL #擷取更新所有欄位的SQL語句(根據主鍵更新) def GetUpdateAllSQL(self): theSQL =self._GetClassValue(EntityB.UpdateAllSqlName) if (theSQL==None or theSQL==‘‘): EntityB.UpdateAllCondition.acquire() try: if EntityB.UpdateAllLockSign: EntityB.UpdateAllCondition.wait() UpdateAllLockSign = True theSQL =self._GetClassValue(EntityB.UpdateAllSqlName) if (theSQL==None or theSQL==‘‘): theTableName=self.GetTableName() theFields=self.GetFields() theKeyField=self.GetKeyField() if theTableName==‘‘ or theFields==[] or theKeyField==‘‘: raise CustomError(‘表名、主鍵或欄位為空白!‘) theSQL=‘UPDATE ‘+ theTableName +‘ SET ‘ theFlds=‘‘ theFldParams = self.GetFieldParams() for theF in theFields: if(theF != theKeyField): if theFlds==‘‘: theFlds += theF+‘= ‘+theFldParams[theF][‘DSFmt‘] else: theFlds += ‘,‘+theF+‘= ‘+theFldParams[theF][‘DSFmt‘] theSQL+= theFlds +‘ WHERE ‘+theKeyField+‘=‘+theFldParams[theKeyField] self._SetClassValue(EntityB.UpdateAllSqlName,theSQL) return theSQL finally: UpdateAllLockSign=False EntityB.UpdateAllCondition.notify() EntityB.UpdateAllCondition.release() else: return theSQL #擷取預設的查詢SQL def GetDefaultSelectSQL(self): theTableName=self.GetTableName() return ‘SELECT * FROM ‘ + theTableName + ‘ WHERE 1=1‘ #def __delitem__(self)
有關實體的通用操作SQL都是動態產生的,但不是每次都去產生,而是緩衝在類型下。所為實體,做如下建議:
1)通用的SQL可以先產生,或者動態產生,但緩衝;
2)一般查詢SQL,特別是帶條件的,盡量不要動態產生,也不要使用類似EF架構的那種,無論是管理效能還是擴充都是災難;
3)一般不要把實體關聯固化,如早期Hibernate的那種方式,就是在資料庫裡也不要建外間關係,去根據業務需要轉化為商務邏輯,一般系統大一點,或者在分布式結構下,去固化實體關聯,或者把實體關聯映射放到記憶體或者設定檔中,都是一種災難。
下面的類是協助工具輔助類:
#Generate entitiesimport BusinessBasedef GetFmtStr(datatype): if datatype.find(‘varchar‘)>=0: return ‘%s‘ elif datatype.find(‘date‘)>=0: return ‘%s‘ else: return ‘%s‘def IntToStr(iData=0): if iData==None: return ‘0‘ return ‘%d‘ % iData;theFile = open(r"EntitiesL.py", "w")try: theDb = BusinessBase.BusinessBase(object) #這裡需改為從你自己的資料庫XXXX theTabs = theDb.GetDbTables(‘XXXX‘) theFile.write("import EntityBase\n") for theTab in theTabs: theFile.write(‘class M_‘+theTab.TableName.upper()+‘(EntityBase.EntityB):\n‘) theFile.write(‘ def __init__(self):\n‘) theFile.write(‘ M_‘+theTab.TableName.upper()+‘.Count += 1\n‘) theFile.write(‘ self.RefDict={}\n‘) theFile.write(‘ self.CurrFields=[]\n‘) theFile.write(‘ Count=0\n‘) theFile.write(‘ TableName =\‘‘+theTab.TableName+‘\‘\n‘) theKeyField=‘‘ theFlds=‘‘ theFile.write(‘ FieldParams={\n‘) theFields=theDb.GetTabFields(‘tian‘,theTab.TableName) theIndex =0 for theF in theFields: if theF.iskey==1: theKeyField = theF.column_name theIndex += 1 if(theIndex>1): theFile.write(‘ ,\n‘) theFlds+=‘,\‘‘+theF.column_name+‘\‘‘ else: theFlds=‘\‘‘+theF.column_name+‘\‘‘ theFile.write(‘ \‘‘+theF.column_name+‘\‘:\n‘) theFile.write(‘ {\n‘) theFile.write(‘ \‘DSFmt\‘:\‘‘+GetFmtStr(theF.data_type)+‘\‘,\n‘) theFile.write(‘ \‘DataType\‘:\‘‘+theF.data_type+‘\‘,\n‘) theFile.write(‘ \‘Length\‘:‘+IntToStr(theF.lengthb)+‘,\n‘) theFile.write(‘ \‘Precision\‘:‘+IntToStr(theF.precisionlen)+‘,\n‘) theFile.write(‘ \‘Scale\‘:‘+IntToStr(theF.scalelen)+‘\n‘) theFile.write(‘ }\n‘) theFile.write(‘ }\n‘) theFile.write(‘ KeyField =\‘‘+theKeyField+‘\‘\n‘) theFile.write(‘ Fields =[‘+theFlds+‘]\n‘) finally: theFile.close()
#這個類用於擷取對象的自訂屬性。
import inspectimport typesclass ObjOpt: @staticmethod def IsProperty(obj): if(obj.__class__ is types.FunctionType): return False else: return True @staticmethod def GetPropertyNames(obj): theAttrs = inspect.getmembers(obj,ObjOpt.IsProperty) theRetAttrs = [] for attr in theAttrs: bb=attr[0].startswith(‘__‘) if bb==False: theRetAttrs.append(attr[0]) return theRetAttrs; #擷取類名 @staticmethod def GetClassName(Obj): return Obj.__name__
這是一個自動產生的實體類例子:
class M_SS01_SYS_USR(EntityBase.EntityB): def __init__(self): M_SS01_SYS_USR.Count += 1 self.RefDict={} self.CurrFields=[] Count=0 TableName =‘SS01_SYS_USR‘ KeyField=‘USR_ID‘ Fields=[‘USR_ID‘,‘USR_NAME‘,‘USR_PWD‘] FieldParams={‘USR_ID‘: { ‘DSFmt‘:‘%s‘, ‘DataType‘:‘varchar‘, ‘Length‘:50, ‘Precision‘:0, ‘Scale‘:0 }, ‘USR_NAME‘: { ‘DSFmt‘:‘%s‘, ‘DataType‘:‘varchar‘, ‘Length‘:50, ‘Precision‘:0, ‘Scale‘:0 }, ‘USR_PWD‘: { ‘DSFmt‘:‘%s‘, ‘DataType‘:‘varchar‘, ‘Length‘:50, ‘Precision‘:0, ‘Scale‘:0 } }
一個簡單的python MVC架構(1)