#Coding:utf-8##Python MySQL ORM quickorm hacking#Description:#previously only knew that there was an ORM, but the internal workings of the ORM thing were not very clear,#this time we need to use it, so I read a relatively simple example of Python2 orm. ##Reference Source:#A Simple ORM provides elegant API for python-mysql operation#Https://github.com/2shou/QuickORM##2016-10-15 Shenzhen Nanshan Ping Shan village ZengjianfengImportMySQLdb##as a domain corresponding to a field in a database, as well as a class attribute# classField (object):PassclassExpr (object):#composition where query part def __init__(self, model, Kwargs): Self.model=Model#How to deal with a non-dict parameter? #extract the value portion of a key-value pairSelf.params =kwargs.values ()#extracts the key part of a value pair and synthesizes the substitution stringequations = [key +'=%s' forKeyinchKwargs.keys ()] self.where_expr='where'+' and'. Join (equations)ifLen (equations) > 0Else "' defUpdate (Self, * *Kwargs): _keys=[] _params= [] #Filter Data forKey, ValinchKwargs.iteritems ():ifVal isNoneorKey not inchSelf.model.fields:Continue_keys.append (Key) _params.append (Val)#Union of values data for key-value pairs in __init___params.extend (self.params)#Synthetic Query Statementssql ='Update%s set%s%s;'%(self.model.db_table,', '. join ([key +'=%s' forKeyinch_keys]), self.where_expr)returndatabase.execute (SQL, _params)defLimit (self, rows, offset=None):#Synthetic limit data, this is where the composition wants to start fetching data from that line, how much data to takeself.where_expr + ='Limit%s%s'% ( '%s,'% OffsetifOffset is notNoneElse "', rows)return SelfdefSelect (self):#Synthetic query statements, fields that require querying, indicate that the conditionsql ='Select%s from%s%s;'% (', '. Join (Self.model.fields.keys ()), self.model.db_table, self.where_expr)#take out all of the data, where yield is used, so that select can be iterated over for the in syntax to get the value forRowinchdatabase.execute (SQL, Self.params). Fetchall ():#gets the type of template passed in so you don't have to know what class ran the SelectInst =Self.model ()#gets the value in a message forIDX, FinchEnumerate (Row): SetAttr (Inst, Self.model.fields.keys () [IDX], F)yieldInst#returns the total number of data statistics for a query defcount (self): SQL='Select COUNT (*) from%s%s;'%(Self.model.db_table, self.where_expr) (row_cnt,)=database.execute (SQL, Self.params). Fetchone ()returnrow_cntclassMetamodel (type): Db_table=None Fields= {} def __init__(CLS, name, bases, Attrs): Super (Metamodel, CLS).__init__(name, bases, Attrs) fields= {} #The class attributes are extracted from all the properties of the class, corresponding to the fields in the database, and are used more for the expr class. forKey, ValinchCls.__dict__. Iteritems ():ifIsinstance (Val, Field): Fields[key]=Val Cls.fields=Fields Cls.attrs=AttrsclassModel (object):#using Metamodel to build model classes __metaclass__=Metamodel#dynamically generate the corresponding SQL statement and execute the corresponding statement, note that this is the instance property that self.__dict__ gets. defSave (self): Insert='Insert ignore into%s (%s) values (%s);'%(self.db_table,', '. Join (self.__dict__. Keys ()),', '. Join (['%s'] * Len (self.__dict__))) returnDatabase.execute (Insert, self.)__dict__. VALUES ())#use where to query@classmethoddefWHERE (CLS, * *Kwargs):returnExpr (CLS, Kwargs)classDatabase (object): Autocommit=True Conn=None Db_config= {} #setting the value of a connected database by Db_config dictionary data@classmethoddefConnect (CLS, * *db_config): Cls.conn= MySQLdb.connect (Host=db_config.get ('Host','localhost'), Port=int (Db_config.get ('Port', 3306)), user=db_config.get ('User','Root'), Passwd=db_config.get ('Password',"'), DB=db_config.get ('Database','Test'), Charset=db_config.get ('CharSet','UTF8') ) Cls.conn.autocommit (cls.autocommit) cls.db_config.update (db_config)#here is the connection database, there are some strategies, such as: #1. If the database is not connected, connect to the database; #2. If the database is connected, then the test can ping and return the connection; #3. If the ping does not pass, reconnect and return. @classmethoddefGet_conn (CLS):if notCls.connor notCls.conn.open:cls.connect (**cls.db_config)Try: cls.conn.ping ()exceptMySQLdb.OperationalError:cls.connect (**cls.db_config)returnCls.conn#here is the direct execution of the SQL statement, which returns the cursor after execution@classmethoddefExecute (CLS, *args): Cursor=cls.get_conn (). Cursor () Cursor.execute (*args)returncursor#called when the object is reclaimed by the garbage collector def __del__(self):ifSelf.conn andself.conn.open:self.conn.close ()#execute the original SQL statementdefExecute_raw_sql (SQL, params=None):returnDatabase.execute (SQL, params)ifParamsElseDatabase.execute (SQL)
Python MySQL ORM Quickorm hacking