Python Learning-writing Your own ORM (2)

Source: Internet
Author: User
Tags rowcount

The previous article simply implemented the ORM (Object Relational model), this article mainly implements the simple MySQL database operation.

To operate the database, first establish a database connection. The following defines a function that creates a database connection, and gets a connection called the engine.

def create_engine (user,password,database,host= ' 127.0.0.1 ', port=3306,**kw):    import mysql.connector    Global Engine    If engine isn't None:        raise Dberror (' engine is already initialized. ')    params = Dict (user=user,password=password,database=database,host=host,port=port)    defaults = Dict (use_unicode= true,charset= ' UTF8 ', collation= ' utf8_general_ci ', Autocommit=false)    #print ('%s%s%s%s ')% (User,password, Database,host,port) for    k,v in Defaults.iteritems ():        params[k] = Kw.pop (k,v)    params.update (kw)    params[' buffered ' = True    engine = Mysql.connector.connect (**params)    cursor = Engine.cursor ()

With the connection, you can manipulate the database. Several functions are written below to query and insert the database.

def _select (Sql,first,*args): cursor = None sql = sql.replace ('? ', '%s ') global engine try:cursor = ENG Ine.cursor () Cursor.execute (Sql,args) If cursor.description:names = [x[0] for x in CURSOR.DESCRI            Ption] If first:values = Cursor.fetchone () if not Values:return None            Return Dict (names,values) return [Dict (names,x) for x in Cursor.fetchall ()] finally:if cursor: Cursor.close () def select_one (Sql,*args): Return _select (Sql,true,*args) def select (Sql,*args): Return _select (S Ql,false,*args) def _update (Sql,*args): cursor = None global engine sql = Sql.replace ('? ', '%s ') print SQL TR        Y:cursor = Engine.cursor () cursor.execute (Sql,args) R = Cursor.rowcount Engine.commit () return r finally:if cursor:cursor.close () def insert (table,**kw): cols, args = Zip (*kw.iteritem s ()) sql = ' Insert inTo%s (%s) values (%s) '% (table, ', '. Join (['%s '% col for Col in Cols]), ' ". Join (['? ' For I in Range (len (cols))]) print (' SQL%s args%s '% (SQL, str (args)) ') return _update (Sql,*args)

Here, the basic database operation has been completed. But, according to Liaoche's tutorial, this is far from enough.

    • If you want to implement multiple operations in a database connection, the code above is inefficient, and you will need to reassign a connection if you do not play one statement at a time.
    • It is equally inefficient to perform multiple operations in a single transaction.
    • If the server allocates a thread for different user database requests, the connection is available for use in the process. This is the problem, causing the database operation to be abnormal.

For the third problem, you should make each connection owned by each thread, and other threads cannot access it, using threading.local. First define a class to hold the context of the database:

Class _dbctx (threading.local):    def __init__ (self):        self.connection = None        self.transactions = 0    def Is_init (self):        return not Self.connection was None    def init (self):        self.connection = engine # Create a database connection        self.transactions = 0    def cleanup (self):        self.connection.cleanup ()        self.connection = None    def Cursor (self):        return Self.connection.cursor ()

The above code has an error. Because Python's assignment statement simply passes a reference to an object to a variable, as in the code above, self.connection = engine in the init function. Indicates that both self.connection and engine point to a database connection object. If the self.connection is given to cleanup, then the object that the engine points to is also cleanup. is an example:

A is a reference to the class Foo instance, after executing b=a, when executing B.clean (), it should be only B's V value is changed to 0, but execution A.V finds that the value of V also becomes 0.

The following is the final code, just encapsulates the bottom-level database operations, the code is also written very much, although the code is modeled Liaoche.

#-*-Coding:utf-8-*-import time, uuid, Functools, threading, Loggingclass Dict (Dict): "Simple Dict    Access as x.y style. "Def __init__ (Self, names= (), values= (), **kw): Super (Dict, self). __init__ (**kw) for K, V in zip (names , values): self[k] = v def __getattr__ (self, key): Try:return Self[key] except key         Error:raise Attributeerror (r "' Dict ' object have no attribute '%s '"% key) def __setattr__ (self, Key, value): Self[key] = Valueclass dberror (Exception): Passclass multicolumnserror (Exception): Passengine = Noneclass _d Bctx (threading.local): def __init__ (self): self.connection = None self.transactions = 0 def is_init (SE  LF): Return not Self.connection was None def init (self): self.connection = Engine self.transactions = 0 def cleanup (self): self.connection = None def cursor (self): return Self.connection.cursor () dEF create_engine (user,password,database,host= ' 127.0.0.1 ', port=3306,**kw): Import mysql.connector Global engine if    Engine is not a none:raise dberror (' engine is already initialized. ') params = dict (user=user,password=password,database=database,host=host,port=port) defaults = Dict (Use_unicode=true, charset= ' UTF8 ', collation= ' utf8_general_ci ', Autocommit=false) #print ('%s%s%s%s ')% (User,password,database,host,     Port) for k,v in Defaults.iteritems (): params[k] = Kw.pop (k,v) params.update (kw) params[' buffered '] = True  Engine = Mysql.connector.connect (**params) print type (engine) _db_ctx = _dbctx () class _connectionctx (object): Def            __enter__ (self): Self.should_cleanuo = False if not _db_ctx.is_init (): cursor = Engine.cursor () _db_ctx.init () Self.should_cleanup = True return self def __exit__ (self,exctype,excvalue,t Raceback): If Self.should_cleanup: _db_ctx.cleanup () def With_connection (func): @functools. Wraps (func) def _wrapper (*args,**kw): With _connectionctx (): RE    Turn func (*args, **kw) return _wrapperdef _select (sql,first,*args): cursor = None sql = sql.replace ('? ', '%s ')            Global _db_ctx try:cursor = _db_ctx.cursor () cursor.execute (Sql,args) if cursor.description:  names = [x[0] for x in cursor.description] if first:values = Cursor.fetchone () if not Values:return None return Dict (names,values) return [Dict (names,x) for x in Cursor.fetc Hall ()] Finally:if cursor:cursor.close () @with_connectiondef Select_one (Sql,*args): Return _selec  T (Sql,true,*args) @with_connectiondef select_int (Sql,*args): D = _select (Sql,true,*args) If Len (d)! = 1:raise    Multocolumnserror (' Except only one column. ') return d.values () [0] @with_connectiondef Select (Sql,*args): Global engine Print type (engine)    Return _select (Sql,false,*args) @with_connectiondef _update (Sql,*args): cursor = None global _db_ctx sql = sq L.replace ('? ', '%s ') print SQL Try:cursor = _db_ctx.cursor () cursor.execute (Sql,args) R = Curso R.rowcount Engine.commit () return R finally:if cursor:cursor.close () def insert (table, **KW): cols, args = Zip (*kw.iteritems ()) sql = ' insert into%s (%s) ' Values (%s) '% (table, ', '. "Join (['%s '% col for Co L in cols]), ', '. Join (['? ' For I in Range (len (cols)])) ' Print (' sql%s args%s '% (SQL, str) ') Return _update (sq L,*args) Create_engine (user= ' root ', password= ' z5201314 ', database= ' test ') u1 = Select_one (' select * from user where id=? ') , 1) print ' U1 ' Print u1print ' start selet () ... ' U2 = Select (' select * from user ') for item in U2:print ('%s%s '% (item.na me,item.id)) print ' name:%s ID:%s '% (u1.name,u1.id)

Python Learning-writing Your own ORM (2)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.