4

简而言之,过滤器内的所有查询的表名都被重命名为 u0、u1、...,所以我额外的 where 子句不知道要指向哪个表。我希望不必为我可能对这些数据进行子选择的每一种方式手动进行所有查询,我目前的解决方法是将我的额外查询转换为 pk values_lists,但这些确实很慢,而且令人厌恶。

这就是这一切的样子。除了指向 products_product.id 的第一个 sql 行之外,您几乎可以忽略此管理器方法的额外内容的详细信息:

def by_status(self, *statii):
    return self.extra(where=["""products_product.id IN                                                                                                                                                  
        (SELECT recent.product_id                                                                                                                                                                          
          FROM (                                                                                                                                                                                           
            SELECT product_id, MAX(start_date) AS latest                                                                                                                                                   
            FROM products_productstatus                                                                                                                                                                    
            GROUP BY product_id                                                                                                                                                                            
          ) AS recent                                                                                                                                                                                      
          JOIN products_productstatus AS ps ON ps.product_id = recent.product_id                                                                                                                           
          WHERE ps.start_date = recent.latest                                                                                                                                                              
            AND ps.status IN (%s))""" % (', '.join([str(stat) for stat in statii]),)])

这对于仅涉及 products_product 表的所有情况都非常有效。

当我想要这些产品作为子选择时,我会:

Piece.objects.filter(
    product__in=Product.objects.filter(
        pk__in=list(
            Product.objects.by_status(FEATURED).values_list('id', flat=True))))

如何保持查询集的通用能力,但仍使用额外的 where 子句?

4

1 回答 1

3

起初:这个问题对我来说并不完全清楚。您问题中的第二个代码块是您要执行的实际代码吗?如果是这种情况,查询应该按预期工作,因为没有执行子选择。

我假设您想使用第二个代码块而不使用list()围绕子选择的代码块,以防止执行第二个查询。


django 文档在有关额外方法的文档中提到了这个问题。然而,要克服这个问题并不容易。

最简单但最“hakish”的解决方案是观察 django 为您要在 extra 方法中查询的表生成了哪个表别名。只要您始终以相同的方式构造查询(您不更改导致连接的多个extra方法或filter调用的顺序),您就可以依赖此别名的持久命名。

您可以使用以下命令检查将在 DB 查询集中执行的查询:

print Model.objects.filter(...).query

这将显示用于您要查询的表的别名。

于 2010-07-20T20:22:47.660 回答