uliweb中ORM关系属性初始化延迟处理调整

调整的原因:@rainwoods报告说,他对plugs中的forum进行了扩展,向Forum表中添加了一个私有标志属性。但是在执行时报告说:

AttributeError: 'module' object has no attribute 'Forum'

实现的方式就是创建了一个新的app,在其中的models.py中重新定义了Forum,向其中添加了一个新的字段。然后在settings.ini中进行设置,从而实现了Model的替換。

方法是没有问题,替換原有的Model本来就是Uliweb ORM支持的做法,就是这样设计的。但是为什么会报错。经分析,原因就是:

在导入新的models.py时,其中有一个Reference字段,它使用了原来forum中的其它的表,这样,uliorm又会导入原来的models.py,而导入时,会把这个文件中定义的所有Model都导入,这其中就会有一些表又引用了Forum。结果又找到了新的models.py。这其实是一个循环引用,即A在处理中,又导入了B,但是在处理B时又导入了A,但是A本身却没有执行完毕。这些都是因为关系字段造成的,因为它们会在定义Model时就创建属性的实例,在初始化属性时就会再通过get_model()来得到关联的Model。

因此为了解决这一问题,我尝试着将关系属性中对关联表的获取进行了延迟处理。并且规定只是在通过get_model()时进行获取处理。所以在Uliweb的项目中,你总是需要使用get_model()来获得某个Model。

不过这样一来,造成了一个和以前不兼容的地方:例如有一个models.py时,其中有两个Model:ModelA, ModelB,并且在ModelB中有一个对ModelA的关系字段。在导入这个模块时,这两个类的属性都会被实例化。以前,关系字段在实例化时,除了会获得关联的Model类之外,还会直接在关联的Model上绑定反向获取的属性,如ModelB_set。对于ModelA就可以直接使用这个属性来反向查询数据(为什么说是反向呢?因为关系本身是定义在ModelB中的,但是现在ModelA中也自动出现了一个关系属性,所以说反向)。但是优化之后,因为这个处理是延迟了,所以在导入models.py时,ModelA和ModelB中的关系字段对关联Model的处理延迟了,自然不会直接在ModelA上绑定反向获取的属性。所以以前直接通过 get_model('modela')后,就可以直接使用modela.ModelB_set来反向获得数据,但是优化之后就找不到了。所以如果想这样处理,你还需要再 get_model('modelb'),以便能让ModelB的关系属性能够被初始化,并绑定反向获取属性。

这是一个不兼容的地方,但是也仅限于Model定义在一个models.py中的情况。如果原来Model就定义在不同的models.py中,原来的版本也一样不能自动绑定,一样是存在这个问题的。所以这回优化后,也可以算是就统一了。

目前经过一些简单的测试,暂时还没有发现问题。如果在使用中发现问题,及时告诉我进行修改。

你可能感兴趣的:(uliweb中ORM关系属性初始化延迟处理调整)