2010-07-25 2 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 … 

В Джанго большинство это

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

Но как я могу добавить AND "watchlist"."user_id" = … в РЕГИСТРИРУЙТЕСЬ состояние с Джанго ОРМ?

Добавление этого фильтра в фильтр не позволяет получить объекты Post без связанных объектов в списке наблюдения.

ответ

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

Счастливое кодирование.

+2

Похоже acually делает то же самое, что и фильтр(). Например. добавление одного параметра в WHERE, а не в ON, и, следовательно, предоставление пустого результата, если нет объекта просмотра. – HoverHell

+0

Но, на самом деле, хорошая идея. Я пропустил параметр «лишний» графа. Похоже, это работает. – HoverHell

+0

... или нет. «Дополнительно», похоже, имеет несколько другую цель. – HoverHell

2

Короткий ответ: при определенных условиях - да.

При строительстве ЛЕВОЕ СОЕДИНЕНИЕ с GenericForeignKey, Django вызывает GenericRelation.get_extra_restriction, который добавляет дополнительное условие к предложению ON с ограничением «content_type_id».

Для «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

Ты спас мой человек жизни :) –

0

При использовании v2.0 Джанго FilteredRelation

Post.objects.annotate(
    t=FilteredRelation(
     'watchlist', condition=Q(watchlist__user_id=1) 
).filter(t__field__in=...) 
Смежные вопросы