手撸ORM系列

手撸ORM系列

实现了简单的orm框架,在封装好的pymysql及基础上,通过类与对象操作pymysql,对数据库进行管理与一些简单操作。

啥也不说,直接上代码!!!

one

封装好pymysql,是实现orm的基本。

# mysql_control.py

import pymysql

class Mysql:
    # 单例模式
    __instance = None
    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance = object.__new__(cls)
        return cls.__instance

    def __init__(self):
        self.mysql = pymysql.connect(
            host='127.0.0.1',
            port=3306,
            user='root',
            password='root',
            database='orm_demo',
            charset='utf8',
            autocommit=True
        )
        self.cursor = self.mysql.cursor(pymysql.cursors.DictCursor)

    def select(self, sql, args=None):
        print(sql)
        print(args)
        # 提交select语句
        self.cursor.execute(sql, args)

        # 获取查询结果
        res = self.cursor.fetchall()
        return res

    # 提交
    def execute(self, sql, args):

        try:
            print(sql)
            print(args)
            self.cursor.execute(sql, args)

        except Exception as e:
            print(e)

    def close(self):
        self.cursor.close()
        self.mysql.close()

two

封装基本的表字段,简单实现了整型与字符串类型。

# orm.py

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 IntegerField(Field):
    def __init__(self, name, column_type='int', primary_key=False, default=None):
        super().__init__(name, column_type, primary_key, 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)

three

操作pymysql,实现简单的数据库操作。

# orm.py

class Model(dict, metaclass=Myorm):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def __getattr__(self, item):
        return self.get(item)

    def __setattr__(self, key, value):
        self[key] = value

    @classmethod
    def select(cls, **kwargs):
        mysql = mysql_control.Mysql()
        if not kwargs:
            sql = 'select * from %s' % cls.table_name
            res = mysql.select(sql)
        else:
            key = list(kwargs.keys())[0]
            value = kwargs.get(key)
            sql = 'select * from %s where %s=?' % (cls.table_name, key)
            sql = sql.replace('?', '%s')
            res = mysql.select(sql, value)
        return [cls(**r) for r in res]

    def save(self):
        mysql = mysql_control.Mysql()
        fields = []
        values = []
        replace = []
        print(self.mappings)
        for k, v in self.mappings.items():
            fields.append(k)

            values.append(
                getattr(self, v.name, v.default)
            )
            replace.append('?')
        sql = 'insert into %s(%s) values(%s)' % (self.table_name, ','.join(fields), ','.join(replace))
        sql = sql.replace('?', '%s')
        mysql.execute(sql, values)

    def sql_update(self):
        mysql = mysql_control.Mysql()
        fields = []
        values = []
        primary_key = False
        for k, v in self.mappings.items():
            if v.primary_key:
                primary_key = getattr(self, v.name)
            else:
                fields.append(v.name + '+?')
                values.append(getattr(self, v.name))
        sql = 'update %s set %s where %s=%s' % (self.table_name, ','.join(fields), self.primary_key, primary_key)

        sql = sql.replace('?', '%s')
        mysql.execute(sql, values)

four

通过元类,限制表名,主键数量,名称空间。

# orm.py

class Myorm(type):
    def __new__(cls, class_name, class_base, class_attr):
        if class_name == 'Model':
            return type.__new__(cls, class_name, class_base, class_attr)
        table_name = class_attr.get('table_name', class_name)
        primary_key = False
        mappings = {}
        for k, v in class_attr.items():
            if isinstance(v, Field):
                mappings[k] = v
                if v.primary_key:
                    if primary_key:
                        raise TypeError('只能有一个主键')
                    primary_key = v.name

        for key in  mappings.keys():
            class_attr.pop(key)

        if not primary_key:
            raise TypeError('必须有一个主键')
        class_attr['table_name'] = table_name
        class_attr['primary_key'] = primary_key
        class_attr['mappings'] = mappings

        return type.__new__(cls, class_name, class_base, class_attr)

five

到此完事!!!

posted @ 2020-03-30 13:12  SweetJack  阅读(229)  评论(0编辑  收藏  举报