views:

25

answers:

1

model:

class Product(models.Model):
  name = models.CharField(max_length = 128)
  (...)    
  def __unicode__(self):
    return self.name

class Receipt(models.Model):
  name = models.CharField(max_length=128)
  (...)
  components = models.ManyToManyField(Product, through='ReceiptComponent')

  def __unicode__(self):
    return self.name

class ReceiptComponent(models.Model):
  product = models.ForeignKey(Product)
  receipt = models.ForeignKey(Receipt)
  quantity = models.FloatField(max_length=9)
  unit = models.ForeignKey(Unit)
  def __unicode__(self):
    return unicode(self.quantity!=0 and self.quantity or '') + ' ' + unicode(self.unit) + ' ' + self.product.genitive

And now I'd like to get list of the most often useable products:

ReceiptComponent.objects.values('product').annotate(Count('product')).order_by('-product__count'

the example result:

[{'product': 3, 'product__count': 5}, {'product': 6, 'product__count': 4}, {'product': 5, 'product__count': 3}, {'product': 7, 'product__count': 2}, {'product': 1, 'product__count': 2}, {'product': 11, 'product__count': 1}, {'product': 8, 'product__count': 1}, {'product': 4, 'product__count': 1}, {'product': 9, 'product__count': 1}]

It's almost what I need. But I'd prefer having Product object not product value, because I'd like to use this in views.py for generating list.

A: 

If I'm not mistaken this has the same behaviour but with objects?

Product.objects.all().annotate(usecount=Count('receipt_set')).order_by('-usecount')
KillianDS
Well. I don't know why - but you're right ;D (small mistake - not receipt_set but receipt or receiptcomponent - don't ask me which - because both returns identical result ;D
SledgehammerPL
I'm confused. Why it works - dunno. Django is smarter than me.
SledgehammerPL
It's not so complicated, you actually want to get the number of times a product is used. Most people will logically assume: I'll go over all receipts and count products, gives me that number. Actually, the reverse relation, counting every recepit for a product gives exactly the same result :p, that's what I'm using here ;-).
KillianDS
The idea is clear (now ;D), but I'm impressed that Django can guess such data. Looking at "classic" way: Receipt has receiptcomponents, receiptcomponent has product. But how product object "knows" that something have it? It's unimaginable ;D
SledgehammerPL