记一次诡异的bug

  使用django做项目,在视图函数中需要查询,查询前构造一个查询参数的模型来过滤参数防止报错,然后调用模型的方法返回一个字典,包括了所有查询的字段和值,发现只要查询过一次之后,后续的访问查询结果会在之前的查询模型上修改,也就是在view中把模型实例化一次之后,后边的操作都会带着之前的痕迹,如下

模型

class CmdbModel:
    base_model_dict = {
        "inst_id": "",
        "uuid": "",
    }
    model_dict = {}

    def __init__(self,partial, modify, except_keys = None, **kwargs):
        self.__set_model(partial= partial, modify= modify, **kwargs)
        if except_keys:
            for key in except_keys:
                self.model_dict.pop(key)
    
    def __set_model(self, partial=False, modify=False, **kwargs):
        pop_list = [key for key in self.model_dict]
        for k in self.model_dict:
            if k in kwargs:
                self.model_dict[k] = kwargs[k]
                pop_list.remove(k)
        if partial is True:
            for pop_key in pop_list:
                self.model_dict.pop(pop_key)
        if modify is True:
            if "inst_id" in self.model_dict:
                self.model_dict.pop("inst_id")
    def get_model(self):
        return self.model_dict
        
class HostModel(CmdbModel):
    model_dict = dict({
        "host_alias": "",
        "host_cpu": "",
        "host_disk": "",
        "host_health_info": "",
        "comment": "",
        "owner": "",
        "host_system": "",
        "host_env": "",
    }, **CmdbModel.base_model_dict)

 调用

host_model = HostModel(
                partial=True,
                modify=False,
                **query_dict
            )
data,count = host_obj.list(start=start, limit=limit, **host_model.get_model())

就是这样

查了一下发现是因为模型的模块是使用form ... import ... 这样引入的,这样是单例模式证据就是在CmdbModel中增加一个类方法

@classmethod
def test(cls):
    print(cls.__init__)

打印结果如下

<function CmdbModel.__init__ at 0x7f5c2cab9598>
<function CmdbModel.__init__ at 0x7f5c2cab9598>
<function CmdbModel.__init__ at 0x7f5c2cab9598>
<function CmdbModel.__init__ at 0x7f5c2cab9598>
<function CmdbModel.__init__ at 0x7f5c2cab9598>
<function CmdbModel.__init__ at 0x7f5c2cab9598>
<function CmdbModel.__init__ at 0x7f5c2cab9598>
<function CmdbModel.__init__ at 0x7f5c2cab9598>
<function CmdbModel.__init__ at 0x7f5c2cab9598>
<function CmdbModel.__init__ at 0x7f5c2cab9598>

看见了没,所有的init都是同一个地址,证明是单例模式

解决方法就是把self里面的成员不修改了,改成使用局部变量吧

不知道有没有办法强制不使用单例模式呢?

posted @ 2018-09-19 15:18  巫谢  阅读(161)  评论(0编辑  收藏  举报