在管理员中使用中间模型使用多对多的后保存过程

时间:2011-11-28 22:19:26

标签: python django orm entity-relationship

我有一个模型关系,由Django docs中关于ManyToMany与中间模型关系的例子定义。

我知道这通常是如何工作的,但这是一个只使用Django Admin的快速小应用程序,这会导致道路上的轻微碰撞。

这就是我所拥有的:

class Item(models.Model):
    name = models.CharField(blank=True, max_length=100)
    vat_deductable = models.BooleanField(default=True)
    price = models.DecimalField(max_digits=12, decimal_places=2)

    def __unicode__(self):
        return self.name


class Invoice(models.Model):
    customer = models.ForeignKey(Relation)
    date = models.DateField(default=datetime.datetime.today)
    amount = models.DecimalField(max_digits=12, decimal_places=2, blank=True, null=True)
    vat_amount = models.DecimalField(max_digits=12, decimal_places=2, blank=True, null=True)
    is_paid = models.BooleanField(default=False)
    paid_on = models.DateField(blank=True, null=True)
    items = models.ManyToManyField(Item, through='SoldItem')

    def __unicode__(self):
        return unicode(self.customer) + u'_' + unicode(self.date)

class SoldItem(models.Model):
    item = models.ForeignKey(Item)
    invoice = models.ForeignKey(Invoice)
    qty = models.IntegerField(default=1, null=True)

以下是我想做的事情:

保存所有模型后(父模型的新实例,相关模型的任何新实例和中间模型的任何新实例)我想循环遍历与Item相关的所有实例新保存的发票,以便我可以将其价格和增值税添加到两个字段Invoice.amountInvoice.vat_amount

我该怎么做?我已尝试在Invoice模型及其ModelAdmin表单上使用自定义保存方法,但在形成新关系时,这两个地方都没有提供完整的图片。

也许是一个信号?但是哪个?

编辑: 我试过这个解决方案: https://stackoverflow.com/a/2109177/150033

save_m2m确保一切都被保存是有意义的,但是在尝试时似乎总是缺少最新的关系。

1 个答案:

答案 0 :(得分:0)

好的,经过大量研究,我发现其他人解决了这个http://igorsobreira.com/blog/2011/2/12/change-object-after-saving-all-inlines-in-django-admin/

在发票管理员中:

class InvoiceAdmin(admin.ModelAdmin):
    inlines = [
        SoldItemAdmin,
    ]

    def response_add(self, request, new_object):
        obj = self.after_saving_model_and_related_inlines(new_object)
        return super(InvoiceAdmin, self).response_add(request, obj)

    def response_change(self, request, obj):
        obj = self.after_saving_model_and_related_inlines(obj)
        return super(InvoiceAdmin, self).response_change(request, obj)

    def after_saving_model_and_related_inlines(self, obj):
        solditem_changed.send(obj)
        return obj

我们的信号:

solditem_changed = Signal()
@receiver(solditem_changed)
def update_invoice(sender, **kwargs):
    if hasattr(sender, 'solditem_set'):
        total = 0
        for item in sender.solditem_set.all():
            total += item.item.price * item.qty
        sender.amount = total
        sender.save()
    else:
        sender.amount = 0
        sender.save()