2010-02-16 20 views
58

查詢過濾我有這些模型:Django的,從模型法

def Foo(Models.model): 
    size = models.IntegerField() 
    # other fields 

    def is_active(self): 
     if check_condition: 
       return True 
     else: 
       return False 

def Bar(Models.model): 
    foo = models.ForeignKey("Foo") 
    # other fields 

現在我想查詢中有酒吧活躍Foo的是這樣的:

Bar.objects.filter(foo.is_active()) 

我收到錯誤,如

SyntaxError at/
('non-keyword arg after keyword arg' 

我該如何做到這一點?

回答

29

您無法查詢模型方法或屬性。在查詢中使用其中的條件,或者使用列表理解或genex在Python中進行過濾。

+6

或者將您要過濾的值存儲在數據庫字段中,並在需要時進行更新(通常在保存時)。然後,您可以像對待其他字段一樣對其進行過濾/排序。 –

+2

如果我重新使用方法查詢中的條件,我該如何保持DRY?我的方法對我們的業務邏輯非常重要,如果所說的邏輯發生變化,我無法承受我的方法打破。保持乾爽是非常重要的。 – Flowpoke

+0

通過在python中執行它,您引入了潛在的性能弱點,因爲當您使用查詢過濾器時,它在數據庫級別完成,但是當您在Python級別上執行時通常會比較慢。 –

10

不能對方法進行篩選,但如果是富的IS_ACTIVE方法檢查上富的屬性,你可以使用雙下劃線的語法像Bar.objects.filter(foo__is_active_attribute=True)

+0

我得到:無法將關鍵字'is_active_attribute'解析爲字段選項如下:....此處列出的所有變量名稱 – Hellnar

+1

是的,這就是爲什麼我說「如果Foo上的is_active方法檢查屬性...」。篩選僅適用於數據庫字段,不適用於方法。因此,如果is_active *正在檢查方法內的某個屬性*,則可以在篩選器中檢查相同的內容。如果它做更復雜的事情,你是不幸的,需要找到一個不同的解決方案。如果您想要特定的答案,請發佈Foo.is_active()的實際代碼。否則,你會得到的是僞代碼解決方案,你不應該期望逐字地工作。 –

13

我有類似的問題:我使用基於類的查看object_list,我必須按照模型的方法進行過濾。 (存儲數據庫中的信息不是一種選擇,因爲財產是基於時間,我會創建一個cronjob和/或... 沒辦法

我的答案是無效的,我不知道它如何在更大的數據上擴展;但它的工作原理如下:

q = Model.objects.filter(...)... 
# here is the trick 
q_ids = [o.id for o in q if o.method()] 
q = q.filter(id__in=q_ids) 
+4

這是我看到保持DRY的唯一方法,但是它會妨礙大數據集的性能(請記住列表存儲在內存中) – Ben

24

您也可以使用自定義管理器。然後,你可以運行這樣的事情:

Bar.objects.foo_active() 

和所有你需要做的是:

class BarManager(models.Manager): 
    def foo_active(self): 
     # use your method to filter results 
     return you_custom_queryset 

退房的docs

+0

您的代碼是非常好的介紹!謝謝 – doniyor

0
class Page(models.Model): 
    category = models.ForeignKey(Category) 
    title = models.CharField(max_length=128) 
    url = models.URLField() 
... 

class Category(models.Model): 
    ... 
    open = models.BooleanField(default=True) 

也許你可以使用簡單的過濾器,這種類型的條件。

Page.objects.filter(category__open=True)