自制ORM

model里面的成员都是全局变量

model里面为全局变量,以便于再未初始化时可以获取该类的成员,将query、filter方法里面的参数设置为model.field,这样就可以获取该对象的表达式。如:

session.query(TestTable).filter(TestTable.number == item. number)

通过查找TestTable类获取该类的所有字段,可以重载TestTable.number类型来获取表达式。比如重载方法可以写成:

    def __eq__(self, rhs):

        op = OP.IS if rhs is None else OP.EQ

        return Expression(self, op, rhs)

这样就可以将filter中的表达式转换为sql语句。

全局变量与类对象

当设置model对象值后,如该值非对应类型则需抛出异常,这可通过重载__set__方法来实现类型校验。

def __set__(self, instance, value):
        if not value:
            if not self._null:
                raise ValueError(non_null_str(self.field_type, self.__column_name__))
        elif not (isinstance(value, int) or isinstance(value, float) or isinstance(value, str)):
            raise ValueError("IntgerField value must be int, not %s, value:%s" % (type(value), value))

        if isinstance(value, float):
            value = int(value)
        else:
            value = int(value)

        # _logger.info("set value:%s, column_name:%s" % (value, self.__column_name__))
        instance.__dict__[self.__column_name__] = value

查询表达式

每个表达式最后都需要转换为对应SQL语句中的条件,那么model里面的每个字段都包含一个隐藏的列名,且都需将对应的运算符进行重载,将其转换为表达式二叉树(左表达式、运算符、右表达式)。当进行转换时,则只需形成SQL语句即可。

def __eq__(self, rhs):
        op = OP.IS if rhs is None else OP.EQ
        return Expression(self, op, rhs)
# 而表达式定义为:
class Expression(object):
    def __init__(self, lhs, op, rhs):
        self.lhs = lhs
        self.op = op
        self.rhs = rhs

    def __str__(self):
        return "<Expression>lhs:%s, op:%s, rhs:%s" % (self.lhs, self.op, self.rhs)

SQL语句与对象映射

这个是ORM组件的核心,sqlalchemy的原理是将model中的每个字段都列举出来(非select *),并包含前缀表名。当找到查询结果后再根据字段名称反向找到对应的对象,这样就完成了一个映射。由于一个对象的所有字段都是相邻的,这在实现上提供了很大的便利性。

其他情况

分页:在转换SQL语句后添加分页说明;

链式调用:每个filter字段都返回对象本身。

and_, or_表达式:Expression对象的右表达式为列表,拼接时采用递归实现。

嵌套查询:如将一个Query对象作为另一个参数传入,这样2个查询就合并为1个,原理仍然是在拼接SQL语句时判断。

自制ORM涉及技术

Python元编程:将所有model类在初始化时自动添加隐藏字段(列名、表名、默认值、是否为空等);

语法树:将where中的过滤条件保存至表达式,形成语法树。

运算符重载:各种过滤条件重载及__set__等特殊方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值