保存另一个模型的对象时更新值的正确方法

时间:2012-10-16 14:14:16

标签: python django many-to-many signals admin

我想在保存交易时(从管理员)更新交易中涉及的人员余额(债权人和债务人)的价值。这是我的模特:

#models.py
class Person(models.Model):
    first_name = models.CharField(max_length = 30) 
    last_name = models.CharField(max_length = 30) 
    phone_number = models.CharField(max_length = 30) 
    email = models.EmailField('e-mail')
    balance = models.DecimalField(max_digits = 5, decimal_places = 2)

class Transaction(models.Model):
    creditor = models.ForeignKey(Person,related_name = 'creditor')
    debtors = models.ManyToManyField(Person, related_name = 'debtors')
    value = models.DecimalField(max_digits = 5, decimal_places = 2)
    split = models.BooleanField()
    date = models.DateField()

这是我的想法,但我只在交易发生变化时才起作用(第一次保存不起作用):

#admin.py
class PersonAdmin(admin.ModelAdmin):
    list_display = ('first_name','last_name','balance')

class TransactionAdmin(admin.ModelAdmin):
    list_display = ('creditor','value','date')
    list_filter = ('date',)
    date_hierarchy = 'date'
    ordering = ('-date',)
    filter_horizontal = ('debtors',)

    def save_model(self,request,obj,form,change):
            obj.save()
            if obj.split:
                    split_value = obj.value/(obj.debtors.all().count()+1)
                    for debtor in obj.debtors.all():
                            p = Person.objects.get(id = debtor.id)
                            p.balance = p.balance - split_value
                            p.save()
                    p = Person.objects.get(id = obj.creditor.id)
                    p.balance = p.balance + (obj.debtors.all().count())*split_value                     
                    p.save()

admin.site.register(Person,PersonAdmin)
admin.site.register(Transaction,TransactionAdmin)

我是Django的新手,对于这样做的正确方法感到很困惑。我对此表示感谢。

2 个答案:

答案 0 :(得分:0)

您可以使用django's signals创建一个在执行保存后(同步)触发的功能(准确的post-save功能)。

例如:

from django.db.models.signals import post_save
from signals import do_something

class TransactionAdmin(models.Model):
    ...

post_save.connect(do_something, sender=TransactionAdmin)

并在signals.py文件中:

def do_something(sender, instance, created, *args, **kwargs):
    if created and sender == TransactionAdmin:
        ...
    ...

答案 1 :(得分:0)

以下是我在研究这些链接后找到的解决方案:

  1. https://docs.djangoproject.com/en/dev/ref/contrib/admin/
  2. http://reinout.vanrees.org/weblog/2011/11/29/many-to-many-field-save-method.html
  3. Issue with ManyToMany Relationships not updating inmediatly after save
  4. Django manytomany signals?
  5. http://python.6.n6.nabble.com/Process-Related-Object-when-Saving-td4974737.html
  6.    def save_related(self,request,form,formsets,change):
                form.save_m2m()
    
                debtors = form.instance.debtors.all()
                n_debtors = debtors.count()
                creditor = form.instance.creditor
                value = form.instance.value
    
                if form.instance.split:
                        value = value/(n_debtors + 1)
    
                for debtor in debtors:
                        p = Person.objects.get(id = debtor.id)
                        p.balance = p.balance - value
                        p.save()
    
                p = Person.objects.get(id = creditor.id)    
                p.balance = p.balance + n_debtors*value
                p.save()