2011-03-12 53 views
1

基本上,我试图使用一个模型中的数据触发另一个模型中的开关。基于此模型触发另一模型的数据更改(M2M)

如果我的发票对象与文件链接,我希望文件被“锁定”(一个布尔值)。

我发现当我保存发票后,将其与一个文件链接后,它不会注册该invoice_file.count()是> 0 - 直到下一次我打开发票并再次保存它。请注意,我在调用super()之后正在进行评估,所以我觉得最好的情况是混淆。

class Invoice(models.Model): 
... 
invoice_file = models.ManyToManyField(UploadFile, null = True, blank = True) 
    def save(self, *args, **kwargs): 
     print('Invoice: saving!') 
     super(Invoice, self).save(*args, **kwargs) 
     print 'invoice_file count: %i' % self.invoice_file.count() 
     if self.invoice_file.count() > 0: 
      for invoice_file in self.invoice_file.all(): 
       if(invoice_file.locked_status(1)) != 1: raise Exception('Couldn\'t set file locked status to 1 on file %s' % invoice_file.filename) 

这在UploadFile模型触发功能:

class UploadFile(models.Model): 
... 
def locked_status(self, stat): 
    print('Locked status called.') 
    if stat == 1: 
     self.locked = True 
     self.save() 
     return 1 
    elif stat == 0: 
     self.locked = False 
     self.save() 
     return 0 

def save(self, *args, **kwargs): 
    print 'UploadFile: Saving!' 
    super(UploadFile, self).save(*args, **kwargs) 
+0

不知道如何解决你的问题,但尝试使用Django 1.2的m2m更改信号:http://docs.djangoproject.com/en/dev/ref/signals/#m2m-changed – 2011-03-12 00:14:07

+0

谢谢斯派克!有趣的是,你应该提到信号,我只是将它们删除,因为它们混淆了我的代码,我发现它更容易重写save()和delete()。然而,似乎信号提供了更好的控制,我可能会重新安置它们,看看我能否得到不同的结果。感谢您的建议! – Harv 2011-03-12 00:19:16

回答

2

删除以下行:

if self.invoice_file.count() > 0: 

如果你打算做一个数据库命中,你不妨通过检索与发票相关的所有文件来完成。这应该具有检索相关对象的“新鲜”视图的额外好处。

虽然问题可能更深入。在保存包含模型之前,ManyToMany字段无法保存。举个例子:

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! 

invoice_file场不准确命名。它应该被称为invoice_files,因为它是一个集合。在您的Invoice.save方法中,在您将任何UploadFile添加到该集合之前,您试图遍历相关集合。我建议在你的Invoice模型中加入一个方法。

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') 

如果发票与大量文件的关联,而不是使用.all(),你应该做self.invoice_files.filter(locked=False)。无论如何,这可能是值得的,以避免不必要的大量数据库保存。

+0

很棒的回答。谢谢! – Harv 2011-03-12 04:10:43