2010-07-25 98 views
6

是否可以添加由django ORM創建的加入語句的附加條件?在django中加入的附加條件

我需要在SQL什麼是

'SELECT "post"."id", COUNT("watchlist"."id") FROM "post" 
LEFT OUTER JOIN "watchlist" 
    ON ("post"."id" = "watchlist"."post_id" AND "watchlist"."user_id" = 1) 
WHERE "post"."id" = 123 GROUP BY … 

在Django大部分是

Post.objects.annotate(Count('watchinglist')).get(pk=123) 

但我怎麼能添加AND "watchlist"."user_id" = …與Django的ORM JOIN條件?

將其添加到篩選器無法獲取在關注列表中沒有關聯對象的Post對象。

回答

0
Post.objects.annotate(Count('watchinglist')).filter(pk=123).extra(where=['"watchlist"."user_id" = 1']) 

快樂編碼。

+2

看起來它acually做同樣的事情作爲過濾器()。例如。如果沒有監視列表對象,則向WHERE添加一個參數,而不是ON,並因此提供空的結果。 – HoverHell 2010-07-25 12:05:39

+0

但是,其實,好主意。我錯過了Count的'額外'參數。看起來像一個工程。 – HoverHell 2010-07-25 12:16:28

+0

...或者可能不是。 「額外」似乎有不同的目的。 – HoverHell 2010-07-25 12:27:21

2

簡答:在某些條件下 - 是的。

當構造LEFT與GenericForeignKey聯接時,Django調用 GenericRelation.get_extra_restriction,它爲帶有「content_type_id」限制的ON子句增加了額外的條件。

對於「ForeignKey」,該方法也被返回None調用。

如果您設法在特定時間組織您的代碼以獲得適當的限制參數,則可以使用此地點將額外限制放入ON子句中。

class UserForeignKey(models.ForeignKey): 

    def get_extra_restriction(self, where_class, alias, related_alias): 
     field = self.model._meta.get_field('user') 
     cond = where_class() 
     # Here is a hack to get custom condition parameters 
     value = SomeContextManager.get_needed_value() 

     lookup = field.get_lookup('exact')(field.get_col(related_alias), value) 
     cond.add(lookup, 'AND') 
     return cond 

class WatchList(models.Model): 

    user = UserForeignKey(User) 
+0

你救了我的人生:) – 2016-11-13 16:22:12

0

在Django中使用2.0 FilteredRelation

Post.objects.annotate(
    t=FilteredRelation(
     'watchlist', condition=Q(watchlist__user_id=1) 
).filter(t__field__in=...)