我们假设我们使用以下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
是否有任何建议将此架构修改为更好的方法?
答案 0 :(得分:1)
如果没有method_b
返回或更改引用的参数,我就不知道这样做的方法。您应该使用pass a variable by reference的技术,就像传递带参数的类一样。
答案 1 :(得分:1)
您可以传入refrence对象中的args,例如dict / list:
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(...)
答案 2 :(得分: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]