2012-08-27 77 views
3

我正在實施一次性數據導入器,我需要搜索現有的slu。。這些slu are是在一個陣列中。將數組轉換爲OR查詢的最佳實踐方式是什麼?從迭代實現django OR查詢的最佳實踐方法?

我想出了以下內容,這很有效,但感覺像太多的代碼來完成這個簡單的事情。

# slug might be an array or just a string 
# ex: 
slug = [ "snakes", "snake-s" ] # in the real world this is generated from directory structure on disk 

# build the query 
query = MyModel.objects 
if hasattr(slug, "__iter__"): 
    q = Q() 
    for s in slug: 
     q = q.__or__(Q(slug=s)) 
    query = query.filter(q) 
else: 
    query = query.filter(slug=slug) 

回答

4
slug = ["snakes", "snake-s" ] # in the real world this is generated from directory structure on disk 

# build the query 
query = MyModel.objects 
if hasattr(slug, "__iter__"): 
    q_list = [] 
    for s in slug: 
     q_list.append(Q(slug=s)) 
    query = query.filter(reduce(operator.or_, q_list)) 
else: 
    query = query.filter(slug=slug) 
  • q_list = []創建Q條款
  • reduce(operator.or_, q_list)破滅的清單,或運營商
  • 列表

閱讀此:http://www.michelepasin.org/techblog/2010/07/20/the-power-of-djangos-q-objects/

@MostafaR - 當然,如果我們想要(見下文),我們可以將我的整個代碼塊壓碎到一行。儘管如此,它在這個級別上不再可讀。說代碼不是「Pythonic」,僅僅是因爲它沒有變得簡單和愚蠢是愚蠢的。可讀代碼是國王恕我直言。記住我的答案的目的也很重要,即通過操作員技術顯示reduce。我的答案的其餘部分是在原始問題的背景下顯示技術。

result = MyModel.objects.filter(reduce(operator.or_, [Q(slug=s) for s in slug])) if hasattr(slug, "__iter__") else MyModel.objects.filter(slug=slug) 
+1

你可以寫這個更pythonic,就像使用一個生成器語句而不是三個創建q_list的代碼行。 – MostafaR

+0

@MostafaR - 查看我的更新 –

+0

Pythonic代碼不是代碼最少的代碼行,並且您的一行代碼沒有足夠的可讀性。但我確信'q_list = [Q(slug = s)for s in slug)]'在你的答案中比'for'語句更可讀。 – MostafaR

-1

,您張貼不會在很多方面的工作(?但我不知道是否應該更僞代碼),但該代碼從我個人理解,這可能幫助:

MyModel.objects.filter(slug__in=slug) 

應該完成這項工作。

+0

謝謝。不知道爲什麼,但我完成了在文檔頁面跳過__in。 –

+0

這個答案是錯誤的,看看這個例子:''test'in'xxtestxx''返回'True'。所以看來這個解決方案有效,但實際上它會導致一些錯誤。 'in'運算符以'str'和'list'的不同方式工作。 – MostafaR

+0

@MostafaR yep,剛剛發現。謝謝。 –

0

我相信,在這種情況下,你應該使用Django的__in field lookup這樣的:

slugs = [ "snakes", "snake-s" ] 
objects = MyModel.objects.filter(slug__in=slugs) 
+0

該解決方案的問題與schacki的解決方案相同。 – MostafaR

+0

我知道,但是schacki遲了四分鐘:) – Pero

+0

哦,它在我的腦海裏馬上,你只是比我更快的typer :-) – schacki

1
result = MyModel.objects.filter(slug__in=slug).all() if isinstance(slug, list) else MyModel.objects.filter(slug=slug).all()