Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to implement Python ORM Framework

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly introduces the relevant knowledge of how to achieve the Python ORM framework, the content is detailed and easy to understand, the operation is simple and fast, and has a certain reference value. I believe you will gain something after reading this article on how to achieve the Python ORM framework. Let's take a look.

What is ORM?

O is object, which means class object, R is relation, translated into Chinese is relation, which means data table in relational database, M is mapping, which means mapping. In the ORM framework, it helps us to map the class to the data table, which allows us to manipulate the data in the corresponding table through the class and class object. The ORM framework also has a function that can automatically help us generate tables in the database according to the classes we design, saving us the process of creating our own tables.

A sentence understanding is: create an instance object, use the name of the class that created it as the name of the data table, use the class properties that created it to correspond to the fields of the data table, and when operating on the instance object, it can correspond to the MySQL statement.

There is an ORM framework embedded in Django, which does not need to program directly to the database, but defines the model class, and completes the operation of adding, deleting, modifying and querying the data table through the model class and object. And the third-party library sqlalchemy are all ORM frameworks.

First, let's take a look at what we are going to achieve.

Class User (parent omission): uid = ('uid', "int unsigned") name = (' username', "varchar (30)") email = ('email', "varchar (30)") password = (' password', "varchar (30)"). Omit... user = User (uid=123, name='hui', email='huidbk@163.com', password='123456') user.save () # corresponds to the following sql statement # insert into User (uid,username,email,password) values (123 HUIDBKE 163.com 123456)

The so-called ORM is to enable developers to manipulate the database, as when operating objects through xxxx. Attribute = yyyy is as simple as this, which is the original intention of developing ORM.

Implement the insert function in ORM

Simple realization of insert function in ORM through metaclass in Python

#! / usr/bin/python3#-*-coding: utf-8-*-# @ Author: Hui# @ Desc: {using the Python metaclass to simply implement the Insert insertion function of the ORM framework} # @ Date: 2021-05-17 17:02class ModelMetaclass (type): "datasheet model metaclass"def _ _ new__ (mcs, cls_name, bases) Attrs): print (f'cls_name-> {cls_name}') # class name print (f'bases-> {bases}') # inherited class print (f'attrs-> {attrs}') # all attributes in class print () # data table correspondence dictionary mappings = dict () # Filter out the field attribute for k of the corresponding data table V in attrs.items (): # determine whether it is an instance object of the specified StringField or IntegerField # here the simple judgment field is tuple if isinstance (v, tuple): print ('Found mapping:% s = = >% s'% (k) V) mappings [k] = v # delete these field attributes that have been stored in the dictionary for k in mappings.keys (): attrs.pop (k) # reference the previous uid/name/email/password and the corresponding object, Class name # Save attrs with other class attribute names ['_ mappings__'] = mappings # save the mapping of attributes and columns attrs ['_ table__'] = cls_name # assume that the table name and class name are the same return type.__new__ (mcs Cls_name, bases, attrs) class User (metaclass=ModelMetaclass): "" user model class "" # type attribute name table field table field type uid = ('uid',' int unsigned') name = ('username',' varchar (30)') email = ('email',' varchar (30)') password = ('password' " 'varchar (30)') def _ init__ (self, * * kwargs): for name, value in kwargs.items (): setattr (self, name, value) def save (self): fields = [] args = [] for k, v in self.__mappings__.items (): fields.append (v [0]) args.append (getattr (self, k) None)) # Table name table_name = self.__table__ # Fields in the data table fields =', '.join (fields) # data to be inserted args =' '.join ([str (I) for i in args]) # generate the sql statement sql = f "" insert into {table_name} ({fields}) values ({args}) "print (f'SQL: {sql}') def main (): user = User (uid=123, name='hui', email='huidbk@163.com') Password='123456') user.save () if _ _ name__ = ='_ main__': main ()

When User specifies a metaclass, the uid, name, email, and password class attributes are not in the class, but are stored in the dictionary specified by the _ _ mappings__ attribute. These properties of the User class will be transformed into the following

_ _ mappings__ = {"uid": ('uid', "int unsigned") "name": (' username', "varchar (30)") "email": ('email', "varchar (30)") "password": (' password', "varchar (30)")} _ table__ = "User"

The effect of execution is as follows:

Cls_name-> Userbases-> () attrs-> {'_ module__':'_ main__','_ qualname__': 'User',' _ doc__': 'user model class', 'uid': (' uid', 'int unsigned'),' name': ('username',' varchar (30)'), 'email': (' email', 'varchar (30)') 'password': (' password', 'varchar (30)'),'_ init__':, 'save':} Found mapping: uid = = > (' uid', 'int unsigned') Found mapping: name = > (' username', 'varchar (30)') Found mapping: email = > ('email',' varchar (30)') Found mapping: password = = > ('password',' varchar (30)') SQL: insert into User (uid,username,email,password) values (123) Hui,huidbk@163.com,123456) improve the detection of data types

The sql statement translated above is as follows:

Insert into User (uid,username,email,password) values (12345 HUIDBKY 163.comMagol 123456)

Found no, string type in sql statement without quotation marks''

The correct sql statement would be:

Insert into User (uid,username,email,password) values (123, 'hui',' huidbk@163.com', '123456')

So modify the User class to improve the detection of data types

Class ModelMetaclass (type): # here is the same as above, so it is omitted. Pass class User (metaclass=ModelMetaclass): "" user model class "" uid = ('uid', "int unsigned") name = (' username', "varchar (30)") email = ('email', "varchar (30)") password = (' password', "varchar (30)") def _ init__ (self, * * kwargs): for name, value in kwargs.items (): setattr (self, name) Value) # perfect data type checking def save (self) here: fields = [] args = [] for k, v in self.__mappings__.items (): fields.append (v [0]) args.append (getattr (self, k) None) # match the parameter data type to the field type of the data table args_temp = list () for temp in args: if isinstance (temp, int): args_temp.append (str (temp)) elif isinstance (temp) Str): args_temp.append (f "{temp}') # Table name table_name = self.__table__ # Fields in the data table fields =', '.join (fields) # data to be inserted args =' '.join (args_temp) # generate the sql statement sql = f "" insert into {table_name} ({fields}) values ({args}) "print (f'SQL: {sql}') def main (): user = User (uid=123, name='hui', email='huidbk@163.com', password='123456') user.save () if _ name__ = ='_ main__': main ()

The running effect is as follows:

Cls_name-> Userbases-> () attrs-> {'_ module__':'_ main__','_ qualname__': 'User',' _ doc__': 'user model class', 'uid': (' uid', 'int unsigned'),' name': ('username',' varchar (30)'), 'email': (' email', 'varchar (30)') 'password': (' password', 'varchar (30)'),'_ init__':, 'save':} Found mapping: uid = = > (' uid', 'int unsigned') Found mapping: name = > (' username', 'varchar (30)') Found mapping: email = > ('email',' varchar (30)') Found mapping: password = = > ('password',' varchar (30)') SQL: insert into User (uid,username,email) Password) values (123ZHUIZHUIZHI HUIDBKG 163.compositional coding 123456') extracted into the base class #! / usr/bin/python3#-*-coding: utf-8-*-# @ Author: Hui# @ Desc: {using the Python metaclass to implement the Insert insertion function of the ORM framework} # @ Date: 2021-05-17 17:02class ModelMetaclass (type): "" Datasheet model metaclass "" def _ new__ (mcs, cls_name, bases) Attrs): print (f'cls_name-> {cls_name}') # class name print (f'bases-> {bases}') # inherited class print (f'attrs-> {attrs}') # all attributes in class print () # data table corresponding relation dictionary mappings = dict () # filter out the field attribute for k of the corresponding data table V in attrs.items (): # determines whether it is the field attribute of the corresponding data table, because attrs contains all the class attributes # here the simple judgment field is tuple if isinstance (v, tuple): print ('Found mapping:% s = = >% s'% (k) V) mappings [k] = v # delete these field attributes that have been stored in the dictionary for k in mappings.keys (): attrs.pop (k) # reference the previous uid/name/email/password and the corresponding object, Class name # Save attrs with other class attribute names ['_ mappings__'] = mappings # save the mapping of attributes and columns attrs ['_ table__'] = cls_name # assume that the table name and class name are the same return type.__new__ (mcs Cls_name, bases, attrs) class Model (object, metaclass=ModelMetaclass): "" def _ init__ (self, * * kwargs): for name, value in kwargs.items (): setattr (self, name, value) def save (self): fields = [] args = [] for k V in self.__mappings__.items (): fields.append (v [0]) args.append (getattr (self, k, None)) # the parameter data type corresponds to the field type of the data table args_temp = list () for temp in args: if isinstance (temp Int): args_temp.append (str (temp)) elif isinstance (temp, str): args_temp.append (f "{temp}') # Table name table_name = self.__table__ # Fields in the data table fields =', '.join (fields) # data to be inserted args =' '.join (args_temp) # generate sql statement sql = f "" insert into {table_name} ({fields}) values ({args}) "print (f'SQL: {sql}') # execute sql statement #... class User (Model):"user table model class"uid = ('uid'," int unsigned ") name = (' username'") "varchar (30)") email= ('email', "varchar (30)") password= (' password', "varchar (30)") def main (): user = User (uid=123, name='hui', email='huidbk@163.com', password='123456') user.save () if _ name__ = ='_ main__': main () add database driver to execute sql statement

Here we use the pymysql database driver to execute sql statements

Add a static method of get_connection to the Model class to obtain the database connection

Import pymysqlclass Model (object, metaclass=ModelMetaclass): "" def _ _ init__ (self, * * kwargs): for name, value in kwargs.items (): setattr (self, name, value) @ staticmethod def get_connection (): "" get database connection and data cursors: return: conn Cursor "" conn = pymysql.connect (database='testdb', host='localhost', port=3306, user='root', password='123456') return conn, conn.cursor () def save (self): fields = [] args = [] for k V in self.__mappings__.items (): fields.append (v [0]) args.append (getattr (self, k, None)) # the parameter data type corresponds to the field type of the data table args_temp = list () for temp in args: if isinstance (temp Int): args_temp.append (str (temp)) elif isinstance (temp, str): args_temp.append (f "{temp}') # Table name table_name = self.__table__ # Fields in the data table fields =', '.join (fields) # data to be inserted args =' '.join (args_temp) # generate the sql statement sql = f "insert into {table_name} ({fields}) values ({args})" print (f'SQL: {sql}') # execute the sql statement conn Cursor = self.get_connection () ret = cursor.execute (sql) print (ret) conn.commit () cursor.close () conn.close () add database driver to execute sql statement

Here we use the pymysql database driver to execute sql statements

Add a static method of get_connection to the Model class to obtain the database connection

Import pymysqlclass Model (object, metaclass=ModelMetaclass): "" def _ _ init__ (self, * * kwargs): for name, value in kwargs.items (): setattr (self, name, value) @ staticmethod def get_connection (): "" get database connection and data cursors: return: conn Cursor "" conn = pymysql.connect (database='testdb', host='localhost', port=3306, user='root', password='123456') return conn, conn.cursor () def save (self): fields = [] args = [] for k V in self.__mappings__.items (): fields.append (v [0]) args.append (getattr (self, k, None)) # the parameter data type corresponds to the field type of the data table args_temp = list () for temp in args: if isinstance (temp Int): args_temp.append (str (temp)) elif isinstance (temp, str): args_temp.append (f "{temp}') # Table name table_name = self.__table__ # Fields in the data table fields =', '.join (fields) # data to be inserted args =' '.join (args_temp) # generate the sql statement sql = f "insert into {table_name} ({fields}) values ({args})" print (f'SQL: {sql}') # execute the sql statement conn Cursor = self.get_connection () ret = cursor.execute (sql) print (ret) conn.commit () cursor.close () conn.close () Test function

Prepare the database

Prepare database testdb and user data tables first

Create database testdb charset=utf8;use testdb;create table user (uid int unsigned auto_increment primary key, username varchar (30) not null, email varchar (30), password varchar (30) not null)

The user table is structured as follows

+-+ | Field | Type | Null | Key | Default | Extra | +-+- -+ | uid | int (10) unsigned | NO | PRI | NULL | auto_increment | | username | varchar (30) | NO | | NULL | | email | varchar (30) | YES | | NULL | Password | varchar (30) | NO | | NULL | | +-+-+ create model class test class User (Model): "" user table model Class "" uid = ('uid' "int unsigned") name= ('username', "varchar (30)") email= (' email', "varchar (30)") password= ('password', "varchar (30)") def main (): user = User (uid=1, name='hui', email='huidbk@163.com', password='123456') user.save () for i in range (2,10): user = User (uid=i) Name=f'name {I}', email=f'huidbk@16 {I} .com', password=f'12345 {I}') user.save () if _ _ name__ ='_ _ main__': main ()

View database user table data

Mysql > select * from user +-+ | uid | username | email | password | +-+ | 1 | hui | huidbk@163.com | 123456 | | 2 | name2 | huidbk@162.com | 123452 | | 3 | name3 | huidbk@163.com | 123453 | | 4 | name4 | huidbk@164.com | 123454 | 5 | name5 | huidbk@165.com | 123455 | 6 | name6 | huidbk@166.com | 123456 | 7 | name7 | huidbk@167.com | 8 | name8 | huidbk@168.com | 123458 | 9 | name9 | huidbk@169.com | 123459 | +- -+ 9 rows in set (0.00 sec) this is the end of the article on "how to implement the Python ORM Framework". Thank you for reading! I believe you all have a certain understanding of the knowledge of "how to implement the Python ORM framework". If you want to learn more, you are welcome to follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report