views:

156

answers:

3

I have the following problem in django.. I have in models.py

class Proposal(models.Model):
    #whatever....
    credit  =models.FloatField(null=True, blank=True)
    def save():
        #here credit is saved based on some calculation (succesfully)

class Author(models.Model):
    #whatever....
    balance = models.FloatField(null=True,blank=True)
    proposal = models.ManyToManyField(Proposal,null=True,blank=True)


    def save(self, force_insert=False, force_update=True):

        to_add = sum(self.proposal.all().values_list('credit',flat=True)) # a sum of credits
        self.balance = self.balance + to_add # or F(self.balance) + to_add, anyway
        try:
            super(Author, self).save(force_insert, force_update)
        except IntegrityError:
            super(Author, self).save(force_insert=True, force_update=False)

So I create an author from admin and from within the author a proposal, i "save" the proposal object, ok, credit succesfully saved, then i save the author, but no balance updated. This happens if only I re-save the author object..

Any suggestions?

+1  A: 

Let me say that I'm not sure what's going wrong for you, but I don't think it's a good idea to try to do this as you're attempting. It is usually preferable in situations where you calculate one datum from a collection of data to do that on lookup, not on save, and for good reason. Even if the above method worked as you expected it to, you'd still have the problem of having to save an Author object when the Author itself hasn't directly changed. Much better to do something like:

class Author(models.Model):
    proposal = models.ManyToManyField(Proposal,null=True,blank=True)

    def get_balance(self):
        return sum(self.proposal.all().values_list('credit',flat=True))

If you really need the convenience of writing author.balance instead of author.get_balance, consider python properties. If this is a situation where reads are more frequent than writes and you want to optimize for performance, consider caching and marking that the data has changed.

David Berger
A: 

I would expect that on the first call to Author.save, self.proposal.all() would be an empty set. (Surprised it doesn't error actually). Since the Author instance itself hasn't been saved yet, it won't have a primary key and therefore we wouldn't expect to be able to find anything associated with something that doesn't exist yet (from the perspective of the DB).

Brian Luft