仿优酷系统的orm

仿优酷系统项目orm

首先orm分别是

​ object relationship mopping

​ 对象关系映射

是将对象映射成数据表中的一条条记录

类 对应 表明

对象 对应 记录

对象.属性 对应 字段

大体的思路:

首先是字段父类型 Field 属性包含 字段名name, 字段类型column_type , 是否是主键primary_key, 默认值 default

接着:
字符串字段类 StringField

整型字段类型 IntegerField

自定义元类:OrmMetaClass

1.要保证每一张都必须要有表名

2.保证一张表中只能有一个主键

3.将所有的“字段名”与“字段对象”添加到一个独立的字典中(mappings),

再添加到类的名称空间中去, 以key(字段名):value(字段对象)

基本的步骤:
1.首先过滤models类

2.获取table表名,如果传过来的名称空间中有自定义的表名,就用自定义的,否则默认将类名作为表名

3.保证每一张表只能有一个唯一的主键

  • 先给一个空的主键
  • 再创建一个空的mappings集合
  • 遍历里面的class_attr,过滤。。
  • 将所有的字段名与字段对象存进mappings集合中

4.要过滤掉类的名称空间中的重复的字段属性

5.给类的名称空间中,添加table_name, primary_key , mappings

定义父类Models

1.为了在定义每个表对应的类时,不用重复的写 __ init __ 方法,以及不需要确定每张表的字段个数,以及字段的名字,让父类继承dict类

2.用 __ getattr __ 与 __ setattr __,让对象.属性可以取值,对象.属性=属性可以增加或修改属性

示例代码

# 字段的父类
class Field:

    def __init__(self, name, column_type, primary_key, default):
        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)
        #确保表中有主键
        if not primary_key:
            raise TypeError('一个表中必须要有一个主键!')

        # 给类的名称空间中加上表名, 主键和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.cursor.close()
       # 再关数据库连接
       self.mysql_client.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')


posted @ 2019-12-18 17:40  godlover  阅读(227)  评论(0编辑  收藏  举报