Note that there are some explanatory texts on larger screens.

plurals
  1. PODjango - Count a subset of related models - Need to annotate count of active Coupons for each Item
    primarykey
    data
    text
    <p>I have a Coupon model that has some fields to define if it is active, and a custom manager which returns only live coupons. Coupon has an FK to Item.</p> <p>In a query on Item, I'm trying to annotate the number of active coupons available. However, the Count aggregate seems to be counting all coupons, not just the active ones.</p> <pre><code># 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)) </code></pre> <p>The <code>.distinct()</code> and <code>distinct=True</code> bits are there for other reasons - the query is such that it will return duplicates. That all works fine, just mentioning it here for completeness.</p> <p>The problem is that <code>Count</code> is including inactive coupons that are filtered out by the custom manager.</p> <p>Is there any way I can specify that <code>Count</code> should use the <code>live</code> manager?</p> <hr> <h3>EDIT</h3> <p>The following SQL query does exactly what I need:</p> <pre><code>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 &lt;= current_timestamp OR active_date IS NULL) AND (valid_until &gt;= current_timestamp OR valid_until IS NULL) ) GROUP BY data_item.title </code></pre> <p>At least on sqlite. Any SQL guru feedback would be greatly appreciated - I feel like I'm programming by accident here. Or, even better, a translation back to Django ORM syntax would be awesome.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload