イミテーションYoukuのシステムプロジェクトのORM
まず、ORMです
オブジェクト関係のモップ
オブジェクトリレーショナルマッピング
オブジェクトは、データテーブルのレコードにマップされ
クラス対応ショー
オブジェクトの対応するレコード
オブジェクトプロパティに対応するフィールド
一般的な考え方:
最初は、それが主キーPRIMARY_KEY、デフォルトのデフォルト値であるかどうか、フィールド名、フィールドタイプCOLUMN_TYPEの名前が含まれているスーパータイプフィールドの属性フィールドであります
次へ:
StringフィールドクラスStringField
整数フィールドタイプIntegerFieldと
カスタムメタクラス:OrmMetaClass
すべてのテーブルには名前を持たなければならないことを保証するために、1。
テーブルは1つのプライマリキーを持つことができることを確認してください2
3.「フィールド名」の全てと、別の辞書(マッピング)を追加するには、「フィールドオブジェクト」、
値(フィールドオブジェクト):クラスキー(フィールド名)にスペースを追加した名前を追加します。
基本的な手順:
1.第一のフィルタベースのモデル
テーブルの2.のGetテーブル名、テーブルには、テーブル名などのカスタムで、それ以上のカスタム名前空間のパス、それ以外の場合は、デフォルトのクラス名に名前を付ける場合
各テーブルには一つだけのユニークな主キーを持つことができることを確認してください3。
- ヌル主キーを与えます
- そして、マッピングの空のセットを作成します
- 内部class_attrを横断し、濾過しました。。
- コレクション・マッピングに堆積し、すべてのフィールド名とフィールドオブジェクト
4.名前空間内の重複フィールド属性クラスをフィルタリングするには
クラス名にスペースは、TABLE_NAME、PRIMARY_KEY、マッピングを追加します
親クラスモデルの定義
テーブルに対応する各クラスは、と、init __ __書き込み方法、およびテーブルごとのフィールドの数を決定する必要がなく、フィールド名が重複していないときを定義するために1.はとても親クラスは、クラスのdictを継承していること
2. __ __ GETATTRと__ __ SETATTR、オブジェクトをしましょう。プロパティ値オブジェクトを受け取ります。属性=属性はプロパティを追加または変更することができます
サンプルコード
# 字段的父类
class Field:
def __init__(self, name, column_type, primary_key=False, default=None):
self.name = name
self.column_type = column_type
self.primary_key = primary_key
self.default = default
# 字符串字段
class StringField(Field):
def __init__(self, name, column_type='varchar(64)', primary_key=False, default=None):
super().__init__(name, column_type, primary_key, default)
# 整型字段
class IntegerField(Field):
def __init__(self, name, column_type='int', primary_key=False, default=0):
super().__init__(name, column_type, primary_key, default)
# 自定义元类
class OrmMetaClass(type):
def __new__(cls, class_name, class_bases, class_attr):
# 首先过滤掉无用的Models
if class_name == 'Models':
return type.__new__(cls, class_name, class_bases, class_attr)
# 获取table的值,有自定义的用自定义的,没有的话默认用类名来当做表明
table_name = class_attr.get('table_name', class_name)
# 保证每一张表都有唯一的一个主键
primary_key = None
# 创建一个空的集合,用来存放字段名,字段对象
mappings = {}
for k, v in class_attr.items():
if isinstance(v, Field):
if v.primary_key:
if primary_key:
raise TypeError('一个表中只能有一个主键!')
primary_key = k
mappings[k] = v
# 过滤掉重复的字段属性
for i in mappings.keys():
class_attr.pop(i)
# 给类的名称空间中加上表名, 主键和mapping集合
class_attr['table_name'] = table_name
class_attr['primary_key'] = primary_key
class_attr['mappings'] = mappings
# 表的父类
class Models(dict, metaclass=OrmMetaClass):
# 在对象.属性属性不存在时,触发
def __getattr__(self, item):
return self.get(item)
# 在对象.属性=属性值时,触发
def __setattr__(self, key, value):
self[key] = value
# 用户表对应的类
class User(Models):
id = IntegerField(name='id', primary_key=True)
name = StringField(name='name')
age = IntegerField(name='age')
if __name__ == '__main__':
pass
MySQLのコードが示すクラス
import pymysql
# mysql类
class MySql:
__instance = None
# 单例模式
@classmethod
def singleton(cls):
if not cls.__instance:
cls.__instance = cls()
return cls.__instance
# mysql类实例化时生成的数据库连接对象
def __init__(self):
self.mysql_client = pymysql.connect(
user='root',
password='555',
host='127.0.0.1',
port=3306,
charset='utf8',
database='yk_demo',
autocommit=True
)
# 生成的游标对象
self.cursor = self.mysql_client.cursor(
pymysql.cursors.DictCursor
)
# 自定义的查询方法
def select(self, sql, args=None):
try:
self.cursor.execute(sql, args)
res1 = self.cursor.fetchall()
return res1
except Exception as e:
return e
# 自定义的提交sql语句的方法
def execute(self, sql, args=None):
try:
self.cursor.execute(sql, args)
except Exception as e:
print(e)
# 关闭游标和数据库连接
def close(self):
self.mysql_client.close()
self.cursor.close()
if __name__ == '__main__':
# obj1 = MySql.singleton()
# obj2 = MySql.singleton()
# print(id(obj1))
# print(id(obj2))
obj = MySql.singleton()
# res = obj.select('select *from user')
# print(res)
sql = 'insert into user(name) values(%s)'
obj.execute(sql, 'egon')