基于此模型触发另一个模型的数据发生变化(M2M)

发布于 2024-10-21 17:17:39 字数 1217 浏览 4 评论 0原文

基本上,我试图使用一个模型中的数据来触发另一个模型中的切换。

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

我发现当我保存发票时,将其与文件链接后,它不会注册发票_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)

Basically, I am trying to use data from one model to trigger a switch in another model.

If my invoice object is linked with a file, I want the file to be "locked" (a boolean).

I find that when I save the invoice, after linking it with a file, it doesn't register that invoice_file.count() is > 0 - until the next time I open up the invoice and save it AGAIN. Note that I am doing the evaluation after calling super() though, so I find this to be confusing at best.

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)

This triggers a function in the UploadFile model:

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

-黛色若梦 2024-10-28 17:17:39

删除以下行:

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)。无论如何,为了避免大量不必要的数据库保存,甚至可能值得这样做。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文