• 初识orm


    初识orm

    一、什么是orm

    • 介绍
    ORM: 对象关系映射
        将随对象映射成 数据表中的鱼跳跳记录
    
        类--->表名
        对象--->记录
        对象.属性--->字段
        
    # 演示映射关系
    '''
    User table:名字、年龄、性别
        
        class User
        user_obj = User()
        user_obj.name属性
        user_obj.age 属性
    
    '''
    
    • 演示orm以及自定义元类
    # 定义字段类型:每个字段都应该有---> 字段名、字段类型、是否为主键、默认值
    # 字段父类
    #
    # 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
    #
    #
    # # varchar
    # class StringField(Field):
    #     def __init__(self, name, column_type='varchar(64)', primary_key=False, default=None):
    #
    #         super().__init__(name, column_type, primary_key, default)
    #
    #
    #
    #
    # # int
    # class IntegerField(Field):
    #     def __init__(self, name, column_type='int', primary_key=False, default=0):
    #         super().__init__(name, column_type, primary_key, default)
    #
    #
    # #自定义元类
    # '''
    # 解决了三件事:
    # 1、保证一张表必须要有表名
    # 2、保证一张表中只能有一个主键
    # 3、将所有“字段名” 与 “字段对象” 添加到一个独立的字典中(mappings)
    # 以 key(字段名):values(字段对象),添加到类的名称空间中,方便后期使用
    # '''
    #
    # class OrmMetaClass(type):
    #
    #     # def __new__(cls, *args, **kwargs):
    #     #     class_name, class_bases, class_attr = args
    #     #     print(f'类名:{class_name}')
    #     #     print(f'基类:{class_bases}')
    #     #     print(f'类的名称空间:{class_attr}')
    #     def __new__(cls, class_name, class_bases, class_attr):
    #
    #         # 1、过滤Models类
    #
    #
    #
    #
    #
    #
    #
    #
    # class Models(dict, metaclass=OrmMetaClass):
    #
    #     # 对象.属性  没有时触发
    #     def __getattr__(self, item):
    #
    #         return self.get(item)    # # {'name': 'tank', 'pwd': '123'}.get('name')
    #
    #     # 对象.属性 = 属性值  时触发
    #     def __setattr__(self, key, value):
    #
    #         # 给字典添加键值对的方式
    #         self[key] = value
    #
    #
    #
    #
    # # User  用户名 密码
    # class User(Models):
    #
    #     # 用户自定义,表名为 user_info
    #     # table_name = 'user_info'
    #     #
    #     # obj = IntegerField(name='id', primary_key=True)
    #     # print(obj.primary_key)
    #     # print(obj.name)
    #     # print(obj.default)
    #
    #     # IntegerField字段类中的name属性 必须与User表中类属性同名
    #     id = IntegerField(name='id', primary_key=True)
    #     username = StringField(name='username')
    #     password = StringField(name='password')
    
    
    #
    # if __name__ == '__main__':
    #     user_dic = dict({'name': 'tank', 'pwd': '123'})
    #
    #     print(type(user_dic))
    #
    #
    #     user_obj = User(naem='tank', pwd='123')
    #     # print(user_obj)
    #     # print(user_obj.__dict__)
    #     # 问题1 通过对象.属性 的方式无法获取属性值 只能通过字典的取值方式获取 因为继承的是dict字典类
    #     # print(user_obj.name)
    #     # print(user_obj.get('name'))
    #     # print(user_obj['name'])
    #     # print(type(user_obj))
    #
    #     # 问题2:继续的字典无法通过  对象.属性的 取值方式  , 对象.属性 = 属性值 增加或修改属性的操作
    #     # 解决2: __getattr__解决了取值方式,__setattr__解决了增加或修改属性的方式
    #     # print(user_obj.name)
    #
    #     print(user_obj.__dict__)
    #     print('添加属性前:--->', user_obj)
    #
    #
    #     # User 类实例化出来的 user_obj 普通对象 添加属性的方式
    #     user_obj.user_type = 'admin'
    #     print(user_obj.__dict__)
    #
    #     print('添加属性后:--->', user_obj)
    
    
    
    
    
    
    
    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
    
    
    # varchar
    class StringField(Field):
        def __init__(self, name, column_type='varchar(64)', primary_key=False, default=None):
            super().__init__(name, column_type, primary_key, default)
    
    
    # int
    class IntegerField(Field):
        def __init__(self, name, column_type='int', primary_key=False, default=0):
            super().__init__(name, column_type, primary_key, default)
    
    
    # 自定义元类
    '''
    解决了三件事:
    1、保证一张表必须要有表名
    2、保证一张表中只能有一个主键
    3、将所有“字段名” 与 “字段对象” 添加到一个独立的字典中(mappings)
    以 key(字段名):values(字段对象),添加到类的名称空间中,方便后期使用
    '''
    
    from mysql_control import MySQL
    
    class OrmMetaClass(type):
    
        # def __new__(cls, *args, **kwargs):
        #     class_name, class_bases, class_attr = args
        #     print(f'类名:{class_name}')
        #     print(f'基类:{class_bases}')
        #     print(f'类的名称空间:{class_attr}')
        def __new__(cls, class_name, class_bases, class_attr):
    
    
    
            # 1、过滤Models类
            if class_name == 'Models':
                # 将models类的类名,基类,名称空间原路返回
                return type.__new__(cls,  class_name, class_bases, class_attr)
    
            # 2、获取 table 表名 ,若自定义则获取自定义的表名,没有则默认使用类名做表名
            # dict.get(key) ---> key若有则返回对应的值,若没有则返回默认追 class_name 就是默认值
            table_name = class_attr.get('table_name', class_name)
            # print(table_name)
    
            # 主键值:主键名为:字段名,比如主键是 id字段 ---> id就是主键的名字
            primary_key = None
    
            # 存放字段名与字段对象的字典
            mappings = {}
    
            # 3、保证一张表只能有唯一的一个主键
            # 循环遍历类的名字
            for k, v in class_attr.items():
                # print(k, v)
                # 将字段以外的属性过滤掉
                # 判断当前的v是否是字段对象
                if isinstance(v, Field):
                    # print(k, v)
                    # print(v.__dict__)
                    # 4、将所有 “字段名”  与 “字段对象” 添加到一个独立的字典中(mappings)
                    mappings[k] = v
    
    
                    # 坑
                    # class_attr.pop(k) # 纠正 ,这里当字典被迭代时,不能直接修改其属性
    
                    # 判断字段对象 如果有 主键primary_key, 则为primary_key 变量赋值
                    if v.primary_key:
                        # 若第二次进来,primary_key 有值,证明有主键 ,抛出异常
                        if primary_key:
                            raise TypeError('一张表只能有一个主键')
    
                        # primary_key = k
                        # 给primary_key变量做一个赋值操作
                        primary_key = v.name
    
    
            # 5、过滤掉类名称空间中重复的字段属性
            for key in mappings.keys():
                class_attr.pop(key)
    
    
            # print(table_name)
            # print(mappings)
            # print(class_attr)
    
            if not primary_key:
                raise TypeError('必须要有一个主键!!!')
    
            # 6、给类的名称空间,添加table_name, primary_key, mappings属性
            class_attr['table_name'] = table_name
            class_attr['primary_key'] = primary_key
            class_attr['mappings'] = mappings
    
            # print('*' * 100)
            # print(class_attr)
    
            return type.__new__(cls, class_name, class_bases, class_attr)
    
    
    
    
    
    class Models(dict, metaclass=OrmMetaClass):
    
        # 对象.属性  没有时触发
        def __getattr__(self, item):
            return self.get(item)  # # {'name': 'tank', 'pwd': '123'}.get('name')
    
        # 对象.属性 = 属性值  时触发
        def __setattr__(self, key, value):
            # 给字典添加键值对的方式
            self[key] = value
    
    
    # User  用户名 密码
    class User(Models):
        # 用户自定义,表名为 user_info
        # table_name = 'user_info'
        #
        # obj = IntegerField(name='id', primary_key=True)
        # print(obj.primary_key)
        # print(obj.name)
        # print(obj.default)
    
        # IntegerField字段类中的name属性 必须与User表中类属性同名
        id = IntegerField(name='id', primary_key=True)
        username = StringField(name='username')
        password = StringField(name='password')
    
    
    • mysql_cntrol
    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(
                host = '127.0.0.1',
                port = 3306,
                user = 'root',
                password = '123456',
                charset = 'utf8',
                database = 'orm_demo',
                autocommit = True
            )
    
            self.cursor = self.mysql_client.cursor(pymysql.cursors.DictCursor)
    
        # 自定义查询方法
        def select(self, sql, args= None):
            # 1、先提交查询sql语句
            # select * from tabele;
            # select * from table where id=%s;
            self.cursor.execute(sql, args)
    
            # 2、获取返回的查询结果
            # res ---> [{}, {}]
            res = self.cursor.fetchall()
            return res
    
    
        # 自定义提交sql语句方法, 比如inset ,update
        def execute(self, sql, args):
    
            # 1、提交sql语句
            # insert into table(字段) values(%s);
            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__':
    
        mysal_obj1 = MySQL.singleton()
        mysal_obj2 = MySQL.singleton()
        print(id(mysal_obj1))
        print(id(mysal_obj2))
    
    
    
    
    Only you can control your future You're not alone. You still have family,peopel who care for you and want to save you.
  • 相关阅读:
    PhpPresentation ppt 导出PPT
    Springcloudalibaba学习实践(1) nacos环境搭建&Eureka Server搭建
    Springcloudalibaba学习实践(2) nacos&Eureka Server服务注册实践
    xna 3.1 to xna 4.0 conversion cheat sheet.(转)
    二分查找的越界以及边界值初始化问题
    决策树知识梳理
    论文分类及写作基础
    Cypher 入门笔记
    python字符串拼接
    Spring、Hibernate 事务流程分析Session生命周期
  • 原文地址:https://www.cnblogs.com/yafeng666/p/12063911.html
Copyright © 2020-2023  润新知