如何在models.py中的save方法中获取内联对象

时间:2015-07-15 07:00:17

标签: django django-models django-admin django-modeladmin django-admin-actions

我有班级发票,其中(简化)具有以下属性:

class Invoice(models.Model)
    number = models.CharField(verbose_name="Number", max_length=16)
    issue_date = models.DateTimeField(verbose_name="Issue date", default=datetime.now)
    total = models.FloatField(verbose_name="Total", blank=True, null=True)

然后,我有InvoiceLine类,它代表发票可以拥有的行/行:

class InvoiceLine(models.Model):
    invoice = models.ForeignKey(Invoice, verbose_name="Invoice")
    description = models.CharField(verbose_name="Description", max_length=64)
    line_total = models.FloatField(verbose_name="Line total")

InvoiceLine是Invoice的内联,我想要实现的是,当在管理员中有人用发票线(一个或多个)保存发票时,计算发票总额。我试图通过覆盖方法来实现它:

class Invoice(models.Model)
    number = models.CharField(verbose_name="Number", max_length=16)
    issue_date = models.DateTimeField(verbose_name="Issue date", default=datetime.now)
    total = models.FloatField(verbose_name="Total", blank=True, null=True)

    def save(self, *args, **kwargs):
         invoice_lines = InvoiceLine.objects.filter(invoice=self.id)
         self.total = 0
         for line in invoice_lines:
             self.total=self.total+line.line_total
         super(Invoice, self).save(*args, **kwargs)

问题在于,当我在InvoiceLine中添加元素时,第一次保存并调用functionsave时,内联中的新元素(InvoiceLine)尚未存储,所以当我{{1 ,它们没有被考虑在内。因此,这种方法的唯一方法是节省两次。 我也试过了:

InvoiceLine.objects.filter(invoice=self.id)

但结果相同。任何的想法? 提前谢谢!

2 个答案:

答案 0 :(得分:6)

最后,我在帖子Change object after saving all inlines in Django Admin上找到了它,这对我帮助很大。关键是在admin.py中我已经有了我的类InvoiceHeaderAdmin(admin.ModelAdmin),但我必须放置三个函数才能在保存所有内联后修改total属性:这样,查询{{1之前没有成功的,现在它完美无缺。 Tue函数InvoiceHeaderAdmin如下:

invoice_lines = InvoiceLine.objects.filter(invoice_header=obj.pk)

线索是最后一个功能,其中所有内联都已保存,现在我可以从对象(发票)计算属性并进行修改。

答案 1 :(得分:0)

对碰巧落入此处的其他人进行了一些更新:您链接的article声明了一种引入的方法here,我们可以重写并获得相同的结果。以您的示例为例:

def save_related(self, request, form, formsets, change):
    super(AjudaCustoProjetoAdmin, self).save_related(request, form, formsets, change)
    obj = form.instance
    invoice_lines = InvoiceLine.objects.filter(invoice_header=obj.pk)

    obj.total = 0
    for line in invoice_lines:
        obj.total=obj.total+line.line_total
    obj.save()