我正在开发一个OpenERP环境,但也许我的问题可以从纯Python的角度来回答。我要做的是定义一个类,其“_columns”变量可以从返回相应字典的函数中设置。所以基本上:
class repos_report(osv.osv):
_name = "repos.report"
_description = "Reposition"
_auto = False
def _get_dyna_cols(self):
ret = {}
cr = self.cr
cr.execute('Select ... From ...')
pass #<- Fill dictionary
return ret
_columns = _get_dyna_cols()
def init(self, cr):
pass #Other stuff here too, but I need to set my _columns before as per openerp
repos_report()
我尝试了很多方法,但这些代码反映了我的基本需求。当我执行我的模块进行安装时,我收到以下错误。
TypeError: _get_dyna_cols() takes exactly 1 argument (0 given)
定义_get_dyna_cols
函数时,我需要self
作为第一个参数(甚至在执行之前)。另外,我需要一个对openerp的'cr'游标的引用,以便查询数据来填充我的_columns字典。那么,我该如何调用此函数以便将其分配给_columns
?我可以将哪个参数传递给此函数?
从OpenERP的角度来看,我想我的需求非常明确。所以建议的任何其他方法也是受欢迎的。
答案 0 :(得分:4)
从OpenERP的角度来看,正确的解决方案取决于您实际尝试做的事情,而且您的描述并不十分清楚。
通常,模型的_columns
定义必须是静态的,因为它将由ORM进行内省,并且(除其他外)将导致创建相应的数据库列。您可以在模型的_columns
方法(而非__init__
1 )中设置init
,但这没有多大意义,因为结果不得更改随着时间的推移,(无论如何,只有在初始化模型注册表时才会调用它。)
现在“静态列”规则有一些例外:
如果您只想动态处理虚拟列的读/写操作,只需使用fields.function
类型的列即可。它需要模拟其他字段类型之一,但可以动态地对数据执行任何操作。典型示例将在一些预处理之后将数据存储在其他(实际)列中。官方OpenERP模块中有数百个示例。
当您开发向导模型(TransientModel
的子类,以前为osv_memory
)时,您通常不关心数据库存储,只是想从用户那里获得一些输入,采取相应的行动。
在这种情况下,需要一个完全动态的列集并不罕见,其中列的数量和类型可能在每次使用模型时都会发生变化。这可以通过覆盖一些关键的API方法来模拟动态列`:
fields_view_get
是客户端调用的API方法,用于获取模型的视图(表单/树/ ...)的定义。fields_get
包含在fields_view_get
的结果中,但可以单独调用,并返回带有模型列定义的dict
。search
,read
,write
和create
以访问和更新记录数据,并应优雅地接受或返回列的值在fields_get
通过正确覆盖这些方法,您可以完全实现动态列,但是您需要保留API行为,并在真实静态列或其他模型中自行处理数据的持久性(如果有)。
官方插件中有一些此类动态列集的示例,例如survey
模块中需要根据调查活动的定义模拟调查表。
1 init()
方法仅在安装或更新模型的模块时调用,以便为此模型设置/更新数据库后端。它依赖于_columns
来执行此操作。
答案 1 :(得分:2)
当你在类体中编写_columns = _get_dyna_cols()
时,那个函数调用就在那里,在类体中,因为Python仍在解析类本身。此时,您的_get_dyn_cols
方法只是本地(类体)命名空间中的一个函数对象 - 并且它被调用。
您收到的错误消息是由于缺少self
参数,只有在您将函数作为方法访问时才会插入该参数 - 但此错误消息并不是错误:错误的是您正在进行一个简单的函数调用并期待一个特殊的行为,比如延迟执行。
Python中实现您想要的方式 - 即在访问属性colluns
时使用自动调用方法的方法是使用内置的“属性”。
在这种情况下,请执行以下操作:_columns = property(_get_dyna_cols)
-
这将创建一个名为“columns”的类属性,通过称为“描述符协议”的机制,只要从实例访问该属性,它就会调用所需的方法。
要了解有关内置属性的更多信息,请查看文档:{{3}}