加入django的附加条件

Hov*_*ell 13 python django

是否可以为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 …
Run Code Online (Sandbox Code Playgroud)

在Django中,大部分都是

Post.objects.annotate(Count('watchinglist')).get(pk=123)
Run Code Online (Sandbox Code Playgroud)

但是如何AND "watchlist"."user_id" = …使用django ORM 添加到JOIN条件中?

将其添加到过滤器无法获得在关注列表中没有关联对象的Post对象.

Cha*_*rmy 10

在Django v2.0中使用FilteredRelation

Post.objects.annotate(
    t=FilteredRelation(
        'watchlist', condition=Q(watchlist__user_id=1)
).filter(t__field__in=...)
Run Code Online (Sandbox Code Playgroud)


小智 9

简短的回答:在某些条件下 - 是的.

当构造LEFT JOIN与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)
Run Code Online (Sandbox Code Playgroud)


sim*_*rsh 2

Post.objects.annotate(Count('watchinglist')).filter(pk=123).extra(where=['"watchlist"."user_id" = 1'])
Run Code Online (Sandbox Code Playgroud)

快乐编码。

  • 看起来它实际上与filter() 做了同样的事情。例如,向 WHERE 添加一个参数,而不是向 ON 添加一个参数,因此,如果没有监视列表对象,则提供空结果。 (5认同)