2012-09-25 38 views
1

讓我們假設我們下面的NDB模式:如何修改ndb.Query對象?

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)) 

的問題是,查詢對象是不可變的,因此它不能被method_b修改。此外,根據代碼的特定體系結構,我們不能讓method_b將新查詢返回給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

「我們不能method_b新的查詢返回method_a」 - 爲什麼不?如果您有示例代碼未展示的無形約束條件,則很難提供有用的答案。 –

+0

這是一個基於我的代碼架構的約束,這就是爲什麼我沒有放入示例代碼。問題的關鍵在於找到修改不可變ndb.Query對象的替代方法。 –

+0

但是,如果您向我們展示您的代碼的結構如何,可能會有更好的解決方案。將一個不可變的對象包裝在一個可變的對象中以「通過引用傳遞」是一個討厭的,令人討厭的黑客行爲。 –

回答

1

我不是不必method_b要麼返回或更改引用參數察覺的方式來做到這一點。您應該使用pass a variable by reference的技巧,例如傳遞帶參數的類。

+0

非常感謝!你重定向我的帖子真的很有幫助。 –

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] 
1

您可以在一個refrence對象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(...) 
+0

元組是不可變的。 –

+0

你是對的,我更新了我的答案。 – someone1