Discuss / Python / 先把ORM说清楚比较容易理解

先把ORM说清楚比较容易理解

Topic source

ORM:对象关系映射,最重要的就是记录表名和类名的映射关系,表字段和实例对象属性之间的映射关系,拼接sql时根据映射关系才能知道哪个字段对应哪个值,元类作用只是用来抽取父类,写通用代码的,用装饰器也能做到同样功能

# 装饰器,用来绑定表名
def table(name):
    def wrap(cls):
        cls.__table__ = name
        return cls

    return wrap


# 字段
class Field(object):
    def __init__(self, name):
        self.name = name


class ModelMetaClass(type):
    def __new__(cls, name, bases, attrs):
        # 基类不处理
        if name == "Model":
            return type.__new__(cls, name, bases, attrs)
        # 设置映射关系表
        mappings = {}
        for key, value in attrs.items():
            if isinstance(value, Field):
                mappings[key] = value.name
        attrs["__mappings__"] = mappings
        # 表名,如果没有被装饰,则使用类名小写
        if not attrs.get("__table__"):
            attrs["__table__"] = name.lower()
        # 删除原有的字段
        for key in mappings.keys():
            attrs.pop(key)

        return type.__new__(cls, name, bases, attrs)


class Model(metaclass=ModelMetaClass):
    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)


# 子类没有指定metaclass时使用父类的metaclass,父类也没有则使用type
@table("u_user")
class User(Model):
    # 使用元类创建关联映射
    id = Field("u_id")
    username = Field("u_username")
    password = Field("u_password")

    def save(self):
        # 拼接sql
        fields = []
        places = []
        values = []
        for key, value in self.__mappings__.items():
            fields.append("`%s`" % str(value))
            # places.append("%s")
            places.append("%(" + "%s" % key + ")s")
            values.append(getattr(self, key))
        sql = "insert into `%s` (%s) values (%s)" % (self.__table__, ", ".join(fields), ", ".join(places))
        arg = tuple(values)
        print(sql)
        print(arg)


if __name__ == '__main__':
    user = User(id=1, username="jack", password="12345678")
    user.save()

复制错了,我本来是想写这个。

# coding:UTF-8

class User(object):
    # 表名
    __table__ = "u_user"
    # 成员变量和表字段映射
    __mappings__ = {
        "id": "u_id",
        "username": "u_username",
        "password": "u_password"
    }

    def __init__(self, id, username, password):
        self.id = id
        self.username = username
        self.password = password

    def save(self):
        # 拼接sql
        fields = []
        places = []
        values = []
        for key, value in self.__mappings__.items():
            fields.append("`%s`" % str(value))
            # places.append("%s")
            places.append("%(" + "%s" % key + ")s")
            values.append(getattr(self, key))
        sql = "insert into `%s` (%s) values (%s)" % (self.__table__, ", ".join(fields), ", ".join(places))
        arg = tuple(values)
        print(sql)
        print(arg)


if __name__ == '__main__':
    user = User(id=1, username="jack", password="12345678")
    user.save()

  • 1

Reply