python 怎么写一个ORM呢?

ORM

对象关系映射,把类当成数据库中的表,把类对象当做数据库中的数据,每一个对象就对应表中没有每一条数据,通过对象.属性的方式,获取每条数据的字段值

需要用的知识点

面向对象,单利模式,元类

sql.py 文件

import pymysql

dic = {
    'host': '127.0.0.1',
    'port': 3306,
    'user': 'root',  #  用户名 
    'passwd': 'root',  # 密码
    'db': 'day41',  # 数据库
    'charset': 'utf8',
    'autocommit': True,
}

class Mysql(object):
    _instance = None

    def __init__(self):
        self.conn = pymysql.connect(**dic)
        self.corsur = self.conn.cursor(pymysql.cursors.DictCursor)

    def close_db(self):
        self.corsur.close()
        self.conn.close()

    def select(self, sql, args=None):
        self.corsur.execute(sql, args)
        res = self.corsur.fetchall()
        return res

    def execute(self, sql, args):
        try:
            self.corsur.execute(sql, args)
        except BaseException as e:
            print(e)

    @classmethod
    def singleton(cls):
        if not cls._instance:
            cls._instance = cls()
        return cls._instance

orm.py 文件

from sql import Mysql


class Field(object):
    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(32)', 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=None):
        super().__init__(name, column_type, primary_key, default)


class MateClass(type):
    def __new__(cls, name, obj, attr):
        if name == 'Models':
            return type.__new__(cls, name, obj, attr)
        table_name = attr.get('table_name', name)
        primary_key = None
        mappings = {}

        for k, v in attr.items():
            if isinstance(v, Field):
                if v.primary_key:
                    if primary_key:
                        raise TypeError('just have a primary key')
                    primary_key = v.name

        for k in mappings.keys():
            cls.attr.pop(k)
        if not primary_key:
            raise TypeError('must have a primary key')

        attr['table_name'] = table_name
        attr['primary_key'] = primary_key
        attr['mappings'] = mappings
        return type.__new__(cls, name, obj, attr)


class Models(dict, metaclass=MateClass):
    def __init__(self, **kws):
        super().__init__(**kws)

    def __getattr__(self, item):
        return self.get(item, 'not found key')

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

    @classmethod
    def select(cls, **kws):
        ms = Mysql.singleton()
        if not kws:
            sql = 'select * from %s' % (cls.table_name)
            res = ms.select(sql)
        else:
            k = list(kws.keys())[0]
            v = kws.get(k)
            sql = 'select * from %s where %s = ? ' % (cls.table_name, k)
            sql = sql.replace('?', '%s')
            res = ms.select(sql, v)
        if res:
            return [cls(**r) for r in res]


class Teacher(Models):
    table_name = 'teacher'
    tid = IntegerField(name='tid', primary_key=True)
    tname = StringField(name='tname')


class Course(Models):
    table_name = 'course'
    cid = IntegerField(name='cid', primary_key=True)
    cname = StringField(name='cname')
    teacher_id = IntegerField(name='teacher_id')


class Score(Models):
    table_name = 'score'
    sid = IntegerField(name='sid', primary_key=True)
    student_id = IntegerField(name='student_id')
    course_id = IntegerField(name='course_id')
    num = IntegerField(name='num')


class Student(Models):
    table_name = 'student'
    tid = IntegerField(name='tid', primary_key=True)
    gender = StringField(name='gender', column_type='varchar(1)')
    class_id = IntegerField(name='class_id')
    sname = StringField(name='sname', column_type='varchar(5)')


if __name__ == '__main__':
    s = Student.select(sid=1)
    print(s)
    t = Teacher.select(tid=1)
    print(t)

初级版本 待更新

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值