缺点是,过滤器内的所有查询的表名都被重命名为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子句?
答案 0 :(得分:3)
起初:这个问题对我来说并不完全清楚。问题中的第二个代码块是否是您要执行的实际代码?如果是这种情况,则查询应该按预期工作,因为没有执行子选择。
我假设您希望在子选择周围使用第二个代码块而不使用list()
来阻止执行第二个查询。
django文档引用了此问题in the documentation about the extra method。然而,解决这个问题并不容易。
最简单但最“hakish”的解决方案是观察django为要在额外方法中查询的表生成哪个表别名。只要您始终以相同的方式构造查询(您不会更改导致连接的多个extra
方法或filter
调用的顺序),您可以依赖此别名的持久命名
您可以使用以下方法检查将在数据库查询集中执行的查询:
print Model.objects.filter(...).query
这将显示用于要查询的表的别名。