简体   繁体   中英

Django Aggregation: Sum of Multiplication of two fields that are not in same model

I have three models (Django 1.6.5):

class Vote(models.Model):
    voter  = models.ForeignKey(UserSettings)
    answer = models.ForeignKey(Answer)
    rating = models.IntegerField()

class Answer(models.Model):
    content = models.CharField(max_length=255)

class UserSettings(models.Model): 
    user = models.OneToOneField(User, related_name='settings')
    weight = models.FloatField(default=1.0)

Basically, a user (voter) can vote for an answer by giving a rating. I know how to sum the ratings by answer:

Vote.objects.all().values('answer').annotate(score=Sum('rating'))

The only subtlety is that each voter has a weight (all voters are not equal!) and I want to sum each product rating*weight. I know (from here ) that something like that can be done:

Sum('id',field="field1*field2")

and it would work well if my 2 fields are in the same model but it doesn't work if they are not. In other words, command:

Vote.objects.all().values('answer').annotate(score=Sum('id',field="rating*voter__weight"))

does not work. Any help greatly appreciated!

The problem is that we need the join with another table (in this case UserSettings), so we need "force" the join.

q = Vote.objects.all().filter(voter__settings__weight__gt=0).values("answer").annotate(Sum('id', field='rating*weight'))

To force the join I used the filter clause (In fact I suppose that all the users have a weight greater than 0) but is just used to force the join. Then you can use the weight field.

PD: I think that this problem is solved in the latest version of Django with Conditional Expressions: https://docs.djangoproject.com/es/1.10/ref/models/conditional-expressions/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM