• orm终极大爆炸


    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 StingField(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)
    
    
    from day38.mysql_control import MySQL
    
    class OrmMetaClass(type):
        def __new__(cls, class_name, class_bases, class_attr):   # 将models的类名, 基类,以及类的名称空间传给自定义的元类
            # 1、过滤掉除了我想控制的类以外的其他的类 此时是过滤掉models
            if class_name == 'Models':
    
                # 将models类的类名,基类,类的名称空间原路返回
                return type.__new__(cls, class_name, class_bases, class_attr)
    
            # 2、获取表名,若有自定义表名则用自定义表名,若没有则默认用类名做表名
            table_name = class_attr.get('table_name', class_name)
    
            # 先将主键值设为None
            primary_key = None
    
            # 想把字段名以及字段对象单独存放在一个字典中, 后面在把这个字典添加到类的 名称空间中去
            mappings = {}
    
            # 3、保证一张表只能有唯一的一个主键
            # 循环遍历获得字段 字段对象
            for k, v in class_attr.items():
                # print(k, v)
                if isinstance(v, Field):
    
                    # 4、将所有的 字段名 以及 字段对象 添加到一个独立的字典中
                    mappings[k] = v
            # print(mappings)  查看mappings
    
    
                    # 判断字段对象是否有主键,且主键是否唯一
                    if v.primary_key:
    
                        # 若第二次进来,primary_key 有值,证明已经有一个主键了,抛出一个异常
                        if primary_key:
                            raise TypeError('一张表只能有一个主键')
    
                        # 确定主键名
                        primary_key = v.name
    
    
            # 5、过滤掉类名称空间中与独立字典中重复的字段 已经字段属性
            for key in mappings.keys():
                class_attr.pop(key)
    
    
            if not primary_key:
                raise TypeError('必须要有一个主键')
    
            # 6、再将表名 主键 独立的字典 添加到类的名称空间中去
            class_attr['table_name'] = table_name
            class_attr['primary_key'] = primary_key
            class_attr['mappings'] = mappings
    
            # 7、返回给models类
            return type.__new__(cls, class_name, class_bases, class_attr)
    
    
    
    class Models(dict, metaclass=OrmMetaClass):
    
        # 对象.属性 没有时 触发
        def __getattr__(self, item):
    
            return self.get(item)   # 将属性返回出去  比如将name返回出去
    
        # 对象.属性 = 属性值 时触发
        def __setattr__(self, key, value):
    
            # 给字典添加键值对的方式
            self[key] = value
    
    
        # 查询数据
        @classmethod
        def select_data(cls, **kwargs):   # **的作用是将传过来的打散
            mysql_obj = MySQL()
    
            filed_value = None
            # 若kwargs 为false代表没有查询条件
            if not kwargs:
                # 1、查所有
                # sql = 'select * from 表名'
                sql = f'select * from {cls.table_name}'
    
            else:
                # 获取字段名
                filed_name = list(kwargs.keys())[0]
    
                # 获取字段值
                filed_value = kwargs.get(filed_name)
    
                # 2、根据条件查询
                # select * from 表名 where 字段名 = 字段值;
                sql = f'select * from {cls.table_name} where {filed_name}=?'
                sql = sql.replace('?', '%s')
                # print(filed_value)
    
            res = mysql_obj.select(sql, filed_value)
    
            return [cls(**i) for i in res]  # ---> [{}, {}] --->[onj, obj]
    
    
        # 插入数据
        def insert_data(self):   # ---> user_obj
            mysql_obj = MySQL()
    
            # sql :insert into 表名(字段名1, 字段名2) values(字段值1, 字段值2);
            # 1、表名 ----> self.table_name
            # 2、字段名与字段值 ---> mappings
    
            # 存放字段名的列表
            filed_names = []  # [字段名, 字段名]
    
            # 存放字段值的列表
            filed_values = []  # [字段值, 字段值]
    
            # 设置一个替换值的列表
            replace_list = [] # [?, ?]
    
            for k, v in self.mappings.items():
    
                # 获取字段名,追加到表中
                filed_names.append(v.name)
    
                # 获取字段值,追加到列表中
                filed_values.append(
                    # 反射:根据字符串操作对象中的属性或方法
                    self.get(v.name, v.default)
                    # getattr(self, v.name, v.default)  这个也可以,只是getattr 返回的是__getattr__返回的值。如果没有返回None
                )
    
                replace_list.append('?')
    
            # sql = f'-- insert into {self.table_name}({",".join(filed_names)}) values({",".join(replace_list)})'
            sql = 'insert into %s(%s) values(%s)' % (
                self.table_name, ",".join(filed_names), ",".join(replace_list)
            )
            sql = sql.replace('?', '%s')
    
            mysql_obj.execute(sql, filed_values)
    
    
        # 更新数据
        def update_data(self):
            mysql_obj = MySQL()
    
            # sql :update 表名 set 字段名=字段名 where pk=主键值;
    
            # 主键值
            pk = None
    
            # 存放字段名的列表
            filed_name = []
    
            # 存放字段值的列表
            filed_values = []
    
            for k, v in self.mappings.items():
                # 判断mappings中那一个字段是主键
                if v.primary_key:
                    # 获取主键的值
                    pk = getattr(self, v.name)
    
                else:
                    # 添加字段名
                    filed_name.append(v.name + '=?')
    
                    # 添加字段值
                    filed_values.append(
                        getattr(self, v.name)
                    )
    
            #sql: update User set 字段名=字段值, 字段名=字段值
            # sql: update User set username=?, password=? where pk=1;
    
            sql = 'update %s set %s where %s=%s' %(
                self.table_name,
                ','.join(filed_name),
                self.primary_key,
                pk
            )
    
            sql = sql.replace('?', '%s')
    
            mysql_obj.execute(sql, filed_values)
    
    
    
    class User(Models):
    
        id = IntegerField(name='id', primary_key=True)
        username = StingField(name='username')
        password = StingField(name='password')
    
    
    if __name__ == '__main__':
        # user_obj = User(name='tank')
        # print(user_obj)
        # print(user_obj.name)
    
        # dict = {'name': 'tank'}
        # print(type(dict.keys()))
        # print(list(dict.keys()))
    
        # user_obj = User(username='JASON_DSB', password='123')
        # user_obj.insert_data()
        # 获取Jason对象
        # user_obj = User.select_data(username='大didi')[0]
        # # 修改对象中属性的值,然后再调用update方法更新到数据库中
        # user_obj.username = '大jiji'
        #
        # user_obj.update_data()
        user_obj = User.select_data()
        print(user_obj)
    
    • mysql_pool.py
    自定义一个mysql_pool.py文件
    # pip install DBUtils
    from DBUtils.PooledDB import PooledDB
    import pymysql
    '''
    数据库连接池
    '''
    POOL = PooledDB(
        creator=pymysql,  # 使用链接数据库的模块
        maxconnections=6,  # 连接池允许的最大连接数,0和None表示不限制连接数
        mincached=2,  # 初始化时,链接池中至少创建的空闲的链接,0表示不创建
        maxcached=5,  # 链接池中最多闲置的链接,0和None不限制
        maxshared=3,
        # 链接池中最多共享的链接数量,0和None表示全部共享。
        # PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。
        blocking=True,  # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错
        maxusage=None,  # 一个链接最多被重复使用的次数,None表示无限制
        setsession=[],  # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."]
        ping=0,
        # ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always
        host='127.0.0.1',
        port=3306,
        user='root',
        password='123456', #你们自己的密码是多少就写多少
        database='orm_demo',  # 换成你们自己想要连接的数据库
        charset='utf8',
        autocommit=True
    )
    
    
    • mysql_control.py
    自定义一个mysql_control.py
    import pymysql
    from mysql_pool import POOL
    
    
    # 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()
            self.mysql_client = POOL.connection()
    
            self.cursor = self.mysql_client.cursor(
                pymysql.cursors.DictCursor
            )
    
        # 自定义查询方法
        def select(self, sql, args=None):
            # 1、先提交查询sql语句
            # select * from table;
            # select * from table where id=%s;
            self.cursor.execute(sql, args)
    
            # 2、获取返回的查询结果
            # res ---> [{}, {}]
            res = self.cursor.fetchall()
            return res
    
        # 自定义提交sql语句方法,比如: insert、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()
    
    
    
    Only you can control your future You're not alone. You still have family,peopel who care for you and want to save you.
  • 相关阅读:
    洛谷P3224 [HNOI2012]永无乡 线段树合并
    洛谷P3605 [USACO17JAN]Promotion Counting——线段树合并
    python之三元表达式、列表推导、生成器表达式、递归、匿名函数、内置函数
    python之迭代器、生成器与面向过程编程
    Python之函数对象、函数嵌套、名称空间与作用域、闭包函数、装饰器
    Python之函数基础
    Python之字符编码与文件操作
    Python基本数据类型
    python介绍
    编程基础
  • 原文地址:https://www.cnblogs.com/yafeng666/p/12071261.html
Copyright © 2020-2023  润新知