1

假设我们采用以下 ndb 模型:

class MyModel(ndb.Model):
    x = ndb.StringProperty()
    y = ndb.StringProperty()
    z = ndb.StringProperty(repeated=True)

我们有一个方法可以为上述模型创建一个查询,执行它并获取结果。但是,我们希望此查询能够修改我的其他功能。具体来说,我们有以下几点:

def method_a():
    qry = MyModel.query() 
    values = {'query':qry}
    method_b(**values)
    entities = qry.fetch()

def method_b(**kwargs):
    k = ['a', 'b', 'c']
    qry = kwargs['query']
    qry.filter(MyModel.z.IN(k))

问题是Query对象是不可变的,因此它不能被method_b修改。另外,根据代码的具体架构,我们不能让method_b将新的Query返回给method_a。

关于如何以另一种方式实现上述功能的任何想法?

更新:请检查我的代码架构,如下所示:

首先,在配置文件中,我们指定模块列表以及它们是否启用。这些模块会影响我们要执行的查询的过滤器。

testparams = {
    'Test1': True,
    'Test2': True,
    'Test3': False,
    'Test4': True
}

然后,我们在代码中的某处有一个方法,该方法在执行适当的模块后进行查询。因此,它看起来像这样:

def my_func():
    qry = MyEntity.query()

    # modules
    query_wrapper = [qry]
    values = {'param':'x', 'query_wrapper':query_wrapper} #other values also
    execute_modules(**values)
    # get query and add some more things, like ordering
    entities = query_wrapper[0].fetch()

execute_modules功能如下:

def execute_modules(**kwargs):
    for k in config.testparams:
        if config.testparams[k]:
            if kwargs['param'] == 'x':
                (globals()[k]).x(**kwargs)
            elif kwargs['param'] == 'y':
                (globals()[k]).y(**kwargs)

最后,指示性模块类似于以下内容:

class Test1():
    @classmethod
    def x(cls, *args, **kwargs):
        qry = kwargs['query_wrapper'][0]
        # do some stuff like adding filters
        kwargs['query_wrapper'][0] = qry

有什么建议可以将此架构修改为更好的方法吗?

4

3 回答 3

1

我不知道没有method_b返回或更改引用参数的方法。您应该使用一种技术通过引用传递变量,例如传递带参数的类。

于 2012-09-26T04:01:06.703 回答
1

您可以在 refrence 对象(例如 dict/list)中传入 args:

def modify_query(kwargs):
  kwargs['qry'] = kwargs['qry'].filter(MyModel.z.IN(k))

qry = MyModel.query()
kwargs = {'qry': qry}
modify_query(kwargs)
result = kwargs['qry'].fetch()

应该注意的是,这是一种非常肮脏的方式来完成你想要完成的事情。类似地,如果你传入一个包含一个对象的列表,那么你可以修改所述列表的内容(通过赋值)来修改对象:

def modify_query(list_object):
  list_object[0] = list_object[0].filter(...)
于 2012-09-26T07:41:20.253 回答
0

您可以做一些技巧来用其他对象替换它。例如:

def f(args):
  qry = args[0]
  qry_new = qry.filter(Model.a == 2)
  args[0] = qry_new

qry = Model.query()
args = [qry]
f(args)
qry = args[0]
于 2012-09-25T22:43:26.320 回答