Chr*_*lor 5 sql django orm count aggregates
我有一个优惠券模型,它有一些字段来定义它是否处于活动状态,以及一个只返回实时优惠券的自定义管理器.优惠券有一个FK到项目.
在对项目的查询中,我试图注释可用的有效优惠券的数量.但是,Count聚合似乎在计算所有优惠券,而不仅仅是活跃优惠券.
# models.py
class LiveCouponManager(models.Manager):
"""
Returns only coupons which are active, and the current
date is after the active_date (if specified) but before the valid_until
date (if specified).
"""
def get_query_set(self):
today = datetime.date.today()
passed_active_date = models.Q(active_date__lte=today) | models.Q(active_date=None)
not_expired = models.Q(valid_until__gte=today) | models.Q(valid_until=None)
return super(LiveCouponManager,self).get_query_set().filter(is_active=True).filter(passed_active_date, not_expired)
class Item(models.Model):
# irrelevant fields
class Coupon(models.Model):
item = models.ForeignKey(Item)
is_active = models.BooleanField(default=True)
active_date = models.DateField(blank=True, null=True)
valid_until = models.DateField(blank=True, null=True)
# more fields
live = LiveCouponManager() # defined first, should be default manager
# views.py
# this is the part that isn't working right
data = Item.objects.filter(q).distinct().annotate(num_coupons=Count('coupon', distinct=True))
Run Code Online (Sandbox Code Playgroud)
在.distinct()与distinct=True位是有其他原因-查询是这样的,它会返回副本.这一切都很好,只是在这里提到完整性.
问题在于Count包括由自定义管理器过滤掉的非活动优惠券.
我有什么方法可以指定Count应该使用live经理吗?
以下SQL查询完全符合我的要求:
SELECT data_item.title, COUNT(data_coupon.id) FROM data_item LEFT OUTER JOIN data_coupon ON (data_item.id=data_coupon.item_id)
WHERE (
(is_active='1') AND
(active_date <= current_timestamp OR active_date IS NULL) AND
(valid_until >= current_timestamp OR valid_until IS NULL)
)
GROUP BY data_item.title
Run Code Online (Sandbox Code Playgroud)
至少在sqlite上.任何SQL大师的反馈都会非常感激 - 我觉得我在这里偶然编程.或者,更好的是,回到Django ORM语法的翻译将是非常棒的.
如果其他人也遇到同样的问题,我的解决方法如下:
Items = Item.objects.filter(q).distinct().extra(
select={"num_coupons":
"""
SELECT COUNT(data_coupon.id) FROM data_coupon
WHERE (
(data_coupon.is_active='1') AND
(data_coupon.active_date <= current_timestamp OR data_coupon.active_date IS NULL) AND
(data_coupon.valid_until >= current_timestamp OR data_coupon.valid_until IS NULL) AND
(data_coupon.data_id = data_item.id)
)
"""
},).order_by(order_by)
Run Code Online (Sandbox Code Playgroud)
我不知道我是否认为这是一个“正确”的答案 - 它以可能不可移植的方式完全复制了我的自定义管理器(我不确定可移植性如何current_timestamp),但它确实有效。
| 归档时间: |
|
| 查看次数: |
934 次 |
| 最近记录: |