[Answered ]-Triggering another model's data to change (M2M) based on this model

2👍

Remove the following line:

if self.invoice_file.count() > 0:

If you’re going to do a database hit, you may as well do it by retrieving all of the files associated with an invoice. This should have the added benefit of retrieving a ‘fresh’ view of related objects.

The problem is probably deeper though. ManyToMany fields can not be saved until its containing model has been saved. An example:

class Post(models.Model):
    title = models.CharField(max_length=100)
    commenters = models.ManyToManyField(User)

me = User.objects.get(username='Josh')
p = Post(title="ManyToManyExample")
p.commenters.add(me) # error, Post does not yet have an ID.
p.save()
p.commenters.add(me) # success!

Your invoice_file field is inaccurately named. It should be called invoice_files, since it is a collection. In your Invoice.save method you’re attempting to iterate over a related collection before you’ve added any UploadFiles to that collection. I’d suggest adding a method to your Invoice model.

class Invoice(models.Model):
    ...

    def add_invoice_file(self, uploaded_file):
        self.invoice_files.add(uploaded_file) # error if the Invoice hasn't been saved yet
        for invoice_file in self.invoice_files.all(): 
            status = invoice_file.locked_status(1)
            if status != 1:
                raise Exception('Blah')

If an Invoice is associated with a large number of files, instead of using .all(), you should do self.invoice_files.filter(locked=False). It might even be worth doing that anyway to avoid a whole lot of database saves that are unnecessary.

Leave a comment