Look at the Liaoche of the web framework, is actually encapsulated the web.py, the request to use asynchronous and will aiomysql做
provide the MySQL database asynchronous IO driver, the front-end part of the integration of Jinja. The hardest part of this is the ORM section.
Here is a simple example of ORM.
classUser (Model):__table__='Users'ID= Stringfield (Primary_key=true, default=next_id, ddl='varchar (+)') Email= Stringfield (ddl='varchar (+)') passwd= Stringfield (ddl='varchar (+)') Admin=Booleanfield () name= Stringfield (ddl='varchar (+)') Image= Stringfield (ddl='varchar (+)') Created_at= Floatfield (Default=time.time)
Overall, this is a simple table for the user, integrated with the model class. Then the fields are the various types of field.
1. First look at the fields, which is the field section. The field section is relatively simple, inherits the object, and initializes some fields, in fact there is nothing to say. When assigning values to a field, the parameter is passed in dict format, where is the dict of the type, but the following code changes the original type with __new__, and the meta-class is the class that creates the class, so the field field parameter, will be handled in the Modelmetaclass class.
classModelmetaclass (type):def __new__(CLS, name, bases, attrs):ifname=='Model': returnType.__new__(CLS, name, bases, attrs) TableName= Attrs.get ('__table__', None)orname Logging.info ('found Model:%s (table:%s)'%(name, tableName)) Mappings=dict () fields=[] PrimaryKey=None forKvinchAttrs.items ():ifisinstance (V, Field): Logging.info ('found mapping:%s ==>%s'%(k, V)) Mappings[k]=vifV.primary_key:#Locate the primary key: ifPrimaryKey:RaiseStandardError ('Duplicate primary key for field:%s'%k) PrimaryKey=kElse: Fields.Append (k)if notPrimaryKey:RaiseStandardError ('Primary key not found.') forKinchMappings.keys (): Attrs.pop (k) Escaped_fields= List (Map (LambdaF:''%s ''%f, fields)) attrs['__mappings__'] = Mappings#Saving mappings for properties and columnsattrs['__table__'] =tableName attrs['__primary_key__'] = PrimaryKey#primary Key property nameattrs['__fields__'] = Fields#attribute name except primary keyattrs['__select__'] ='Select '%s ',%s from '%s ''% (PrimaryKey,', '. Join (Escaped_fields), tableName) attrs['__insert__'] ='insert INTO '%s ' (%s, '%s ') values (%s)'% (TableName,', '. Join (Escaped_fields), PrimaryKey, Create_args_string (len (escaped_fields) + 1)) attrs['__update__'] ='Update '%s ' set%s where '%s ' =?'% (TableName,', '. Join (Map (LambdaF:''%s ' =?'% (Mappings.get (f). Nameorf), fields), PrimaryKey) attrs['__delete__'] ='Delete from '%s ' where '%s ' =?'%(TableName, PrimaryKey)returnType.__new__(CLS, name, bases, Attrs)
The model class is relatively simple, mainly in order to initialize the Get/set and a few getvalue functions, this piece according to their own needs to look at good.
classModel (Dict, metaclass=modelmetaclass):def __init__(Self, * *kw): Super (Model, self).__init__(**kw)def __getattr__(self, key):Try: returnSelf[key]exceptKeyerror:RaiseAttributeerror (R"' Model ' object has no attribute '%s '"%key)def __setattr__(self, Key, value): Self[key]=valuedefGetValue (self, key):returngetattr (self, Key, None)defGetValueOrDefault (self, key): Value=getattr (self, Key, None)ifValue isNone:field= self.__mappings__[key]ifField.default is notNone:value= Field.default ()ifCallable (Field.default)ElseField.default Logging.debug ('using default value for%s:%s'%(Key, str (value))) SetAttr (self, key, value)returnvalue @classmethod @asyncio. CoroutinedefFindnumber (CLS, Selectfield, Where=none, args=None):'find number by Select and where.'SQL= ['Select%s _num_ from '%s ''% (Selectfield, CLS.__table__)] ifWhere:sql.append ('where') Sql.append (where) RS=yield fromSelect' '. Join (SQL), args, 1) ifLen (rs) = =0:returnNonereturnrs[0]['_num_']
....
The @classmethod is to turn the method into a class method, @asyncio. Coroutine is to do asynchronous processing.
On the ORM design in Python web framework