zoukankan      html  css  js  c++  java
  • 仿优酷系统的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')
    
    
    
  • 相关阅读:
    sql server delete语句
    sql server 通配符
    sql server join联结
    windows下如何使用两个版本的nodejs
    PHP的Trait 特性
    PHP错误与异常处理try和catch
    laravel belongsTo()&hasOne()用法详解
    Laravel Model 的 fillable (白名单)与 guarded (黑名单)
    js原生,缓动动画封装
    js原生轮播图
  • 原文地址:https://www.cnblogs.com/godlover/p/12061124.html
Copyright © 2011-2022 走看看