zoukankan      html  css  js  c++  java
  • 模拟django orm实现遇到的坑

    """
    核心理念就是:类属性对应为便于用户理解的字段名(如name),而数据库中保存的是另一个字段名(如用户字段名name对应数据库实际
    保存的字段名为username),当调用save时,要将便于用户理解的字段名转化为实际数据库保存的用户名
    """
    
    
    class ModelMetaclass(type):
        def __new__(cls, cls_name, bases, attrs):
            print("*" * 20, cls, " ", cls_name)
            mappings = dict()
            for k, v in attrs.items():
                if isinstance(v, tuple):
                    mappings[k] = v
    
            for k in mappings.keys():
                attrs.pop(k)
    
            attrs["__mappings__"] = mappings
            attrs["__table__"] = cls_name
    
            # 以User为例,User类中的属性,经过元类的改造,就变成下面的__mappings__字典
            # __mapping__ = {
            #     "uid": ("uid", "int unsigned"),
            #     "name": ("username", "varchar(30)"),
            #     "email": ("email", "varchar(30)"),
            #     "password": ("password", "varchar(30)")
            # }
            # __table__ = "User" , 类名就是表名
    
            return type(cls_name, bases, attrs)
    
    
    class Model(metaclass=ModelMetaclass):
        def __init__(self, **kwargs):
            for name, value in kwargs.items():
                setattr(self, name, value)
    
        def save(self):
            fields = []  # 实际保存在数据库中的字段名
            args = []  # 用户传入的值
            for k, v in self.__mappings__.items():
                fields.append(v[0])
                args.append(getattr(self, k, None))
    
            args_temp = list()
            for item in args:
                if isinstance(item, int):
                    args_temp.append(str(item))
                if isinstance(item, str):
                    args_temp.append("""'%s'""" % item)
    
            print(self.__table__, self.__mappings__)
    
            sql = "insert into %s (%s) values (%s)" % (self.__table__, ",".join(fields), ",".join(args_temp))
            print("SQL: %s" % sql)
    
    
    class User(Model):
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
    
        uid = ("uid", "int unsigned")
        name = ("username", "varchar(30)")
        email = ("email", "varchar(30)")
        password = ("password", "varchar(30)")
    
    
    u = User(uid=12345, name="Michael", email="test@orm.org", password="my-pwd")
    u.save()

    目的是类继承Model时就能使用ModelMetaclass去改造之,比如定义了User类,继承了Model,希望在构造User类时,使用ModelMetaclass去做一些自定义的改造,然而发现构造User时根本就没有调用ModelMetaclass.__new__方法,只有构造Model类时调用了ModelMetaclass.__new__方法,奇怪,不是在构造类的时候会去找父类的元类吗?

    找时间把这个坑彻底填了

  • 相关阅读:
    留言板
    移动端开发
    css3的伪类
    JQuery移除事件
    关于offset,你知道多少?
    关于section-scroll插件:
    jQuery响应式弹出层和对话框插插件magnific-popup.css
    col-lg-8 col-lg-offset-2
    关于渐变属 gradient:
    关于 window.onresize
  • 原文地址:https://www.cnblogs.com/olivertian/p/12630936.html
Copyright © 2011-2022 走看看