开发者

Unable to iterate over ManyToMany - how do I calculate the sum?

开发者 https://www.devze.com 2023-04-09 07:49 出处:网络
My models look like this: class Article(models.Model): name = models.CharField(max_length=50) description = models.TextField()

My models look like this:

class Article(models.Model):
name = models.CharField(max_length=50)
description = models.TextField()
price = models.FloatField()

def __unicode__(self):
    return "%s - %s" % (sel开发者_JS百科f.name, self.price)

class Order(models.Model):
client = models.ForeignKey(User)
articles = models.ManyToManyField(Article)
total = models.FloatField(editable=False, blank=True, default=0)

def __unicode__(self):
    return "%s - %s" % (self.client.username, self.total)

def save(self):
    for a in self.articles:
        self.total += a.price
    super(Order, self).save()

And I try to calculate the total price in save(). If I try to save an order via the admin, I get

'Order' instance needs to have a primary key value before a many-to-many relationship can be used

If I call

super(Order, self).save()

before calculating the sum, I get

'ManyRelatedManager' object is not iterable .

I don't know to do... I thought about calculating total in the view, but I would like to store it in my database.

How to I iterate over all the articles in the Order-Model?

Thanks in advance :)


I'd replace your total field with a property:

class Order():
    ....
    @property
    def total(self):
        return self.articles.aggregate(Sum('price'))['price__sum']

the reason is: when you add items to collection your object is not saved again, so it wouldn't update your counter. With this property you'll be sure to always have correct data.


If you really need to do this, you could save the instance first if it has no PK:

def save(self, *args, **kwargs):
    if self.pk is None:
        super(Order, self).save(*args, **kwargs)
    for a in self.articles.all():
        self.total += a.price
    super(Order, self).save(*args, **kwargs)


Use aggregation. Replace

for a in self.articles:
    self.total += a.price

with

from django.db.models import Sum

#..............
self.total = self.articles.aggregate(Sum('price'))['price__sum']
0

精彩评论

暂无评论...
验证码 换一张
取 消