дополнительные условия по вступлению в джанго - PullRequest
12 голосов
/ 25 июля 2010

Можно ли добавить дополнительное условие для оператора объединения, созданного django ORM?

Что мне нужно в 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" = … в состояние JOIN с помощью django ORM?

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

Ответы [ 4 ]

9 голосов
/ 05 октября 2016

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

Когда конструкция LEFT СОЕДИНЯЕТСЯ с 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)
8 голосов
/ 10 января 2018

В Django v2.0 используйте FilteredRelation

Post.objects.annotate(
    t=FilteredRelation(
        'watchlist', condition=Q(watchlist__user_id=1)
).filter(t__field__in=...)
2 голосов
/ 25 июля 2010
Post.objects.annotate(Count('watchinglist')).filter(pk=123).extra(where=['"watchlist"."user_id" = 1'])

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

1 голос
/ 25 июля 2010

Я нашел похожий вопрос здесь: Django - фильтрация по связанным объектам

И, похоже, нет способа сделать это без специального SQL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...