【问题标题】:In Django ForeignKey relationship does not get saved correctly when saving two objects在保存两个对象时,Django ForeignKey 关系没有正确保存
【发布时间】:2012-11-04 09:30:57
【问题描述】:

我有两个代表一对多关系的模型。 InterestRateCurve 对象可以有许多 InterestRate 对象。 问题是,当我有一个创建两条曲线的函数时,每条曲线都有一个速率,第二条曲线的速率会覆盖第一条曲线的速率。所以,我最终在数据库中有两行用于曲线和一行用于速率。 当我执行一个保存一条曲线和一个速率的程序,然后执行一个单独的程序以保存另一条曲线的速率时,一切都很好。

我使用 Python 2.7 和 Django 1.4。

型号:

class InterestRate(models.Model):
    type = models.CharField(max_length=20)
    term = modelFields.tgTimePeriodField(max_length=20)
    numTerms = models.IntegerField()
    mid = models.FloatField()
    curve = models.ForeignKey('InterestRateCurve')

    class Meta:
        unique_together = ('type', 'term', 'numTerms', 'curve')

    def __unicode__(self):
        return "%s/%s/%s/%s" % (self.type, self.term, self.numTerms, self.curve)

    def __str__(self):
        return "%s/%s/%s/%s/%s" % (self.type, self.term, self.numTerms, self.mid, self.curve)


class InterestRateCurve(models.Model):
    ccy = modelFields.tgCurrencyField(max_length=20)
    index = models.CharField(max_length=20)
    term = modelFields.tgTimePeriodField(max_length=20)
    numTerms = models.IntegerField()
    asOf = modelFields.tgDateField()
    cvid = models.CharField(max_length=20, blank=True, default='')
    #rates needs to be explicitly maintained inside class for convenience
    rates = []

    class Meta:
        unique_together = ('ccy', 'index', 'term', 'numTerms', 'asOf', 'cvid')

    def __unicode__(self):
        return "%s/%s/%s/%s/%s/%s" % (self.ccy, self.index, self.term, \
                                      self.numTerms, self.asOf, self.cvid)

    def save(self):
        try:
            curve = InterestRateCurve.objects.get(ccy=self.ccy, index=self.index,\
                                                  term=self.term, numTerms=self.numTerms,\
                                                  asOf=self.asOf, cvid=self.cvid)
            #Delete all rates before saving the new rates
            oldRates = curve.interestrate_set.all()
            for oldRate in oldRates:
                oldRate.delete()
            for rate in self.rates:
                rate.curve = curve
                rate.save()
        except InterestRateCurve.DoesNotExist:
            super(InterestRateCurve, self).save()
            curve = InterestRateCurve.objects.get(ccy=self.ccy, index=self.index,\
                                                  term=self.term, numTerms=self.numTerms,\
                                                  asOf=self.asOf, cvid=self.cvid)
            for rate in self.rates:
                rate.curve = curve
                rate.save()

    def addRate(self, rate):
        rate.curve = self
        exists = False
        for r in self.rates:
            if r.type == rate.type:
                if r.term == rate.term:
                    if r.numTerms == rate.numTerms:
                        exists = True
                        continue
        if exists == False:
            self.rates.append(rate)

以下代码可以正常工作:

        date = tgDate(month=9,day=12,year=2011)
        curve = InterestRateCurve(ccy='USD', index='LIBOR', term='M', 
                                  numTerms=3, asOf=self.asOf, cvid='TESTSAVE2CURVES')
        curve.save()
        curve = InterestRateCurve.objects.get(ccy='USD', index='LIBOR', term='M', 
                                              numTerms=3, asOf=date, cvid='TESTSAVE2CURVES')
        rate = InterestRate(term='M', numTerms=1, type='Deposit', mid=0.01, curve=curve)
        curve.addRate(rate)
        curve.save()

此执行导致一条曲线和一个速率被保存。

在单独的执行中我运行:

        date = tgDate(month=9,day=13,year=2011) #DATE DIFFERS
        curve = InterestRateCurve(ccy='USD', index='LIBOR', term='M', 
                                   numTerms=3, asOf=date, cvid='TESTSAVE2CURVES')
        curve.save()
        curve = InterestRateCurve.objects.get(ccy='USD', index='LIBOR', term='M', 
                                              numTerms=3, asOf=date, cvid='TESTSAVE2CURVES')
        rate = InterestRate(term='M', numTerms=1, type='Deposit', mid=0.01)
        curve.addRate(rate)
        curve.save()

此执行导致另一条曲线和另一个速率保存。

但是,下面的执行不能正常工作:

    def testSave2Curves(self):
        date = tgDate(month=9,day=12,year=2011)
        curve = InterestRateCurve(ccy='USD', index='LIBOR', term='M', 
                                  numTerms=3, asOf=date, cvid='TESTSAVE2CURVES')
        curve.save()
        curve = InterestRateCurve.objects.get(ccy='USD', index='LIBOR', term='M', 
                                              numTerms=3, asOf=date, cvid='TESTSAVE2CURVES')
        rate = InterestRate(term='M', numTerms=1, type='Deposit', mid=0.01, curve=curve)
        curve.addRate(rate)
        curve.save()
        date1 = tgDate(month=9,day=13,year=2011)
        curve1 = InterestRateCurve(ccy='USD', index='LIBOR', term='M', 
                                   numTerms=3, asOf=date1, cvid='TESTSAVE2CURVES')
        curve1.save()
        curve1 = InterestRateCurve.objects.get(ccy='USD', index='LIBOR', term='M', 
                                               numTerms=3, asOf=date1, cvid='TESTSAVE2CURVES')
        rate1 = InterestRate(term='M', numTerms=1, type='Deposit', mid=0.01)
        curve1.addRate(rate1)
        curve1.save()

这导致保存了两条曲线,但只保存了一个速率。似乎第二个速率会覆盖之前保存的第一个速率。

【问题讨论】:

  • 请问,为什么是二流模特rate1,而不是InterestRate(term='M', numTerms=1, type='Deposit', mid=0.01, curve=curve1)
  • lserni,你是对的。我在复制/粘贴时犯了一个错误。它已得到答复并解决。

标签: python django django-models model foreign-keys


【解决方案1】:

问题在于将rates = [] 指定为InterestRateCurve 的类变量。由于这个定义,InterestRateCurve 的每个对象都访问相同的费率列表。

在示例中创建第一条曲线和比率后,InterestRateCurve.rates 包含创建的比率。然后创建第二条曲线并保存。 InterestRateCurve.save() 被执行,跳转到except 分支并执行:

for rate in self.rates:
    rate.curve = curve
    rate.save()

还记得self.rates (= InterestRateCurve.rates) 包含您的第一流吗?循环将此汇率的外键设置为您的第二条曲线并保存。现在,您的第一条曲线不再具有相关比率。您的第一条曲线的速率现在属于第二条曲线。

之后,您创建的第二个汇率与您的第一个汇率具有完全相同的属性。由于您在InterestRate 模型中指定:

class Meta:
    unique_together = ('type', 'term', 'numTerms', 'curve')

...只有一个速率具有完全相同的属性。我不确定是旧的被删除了还是新的没有保存。但是,结果是您在数据库中只有一个速率对象,属于您的第二条曲线。

希望你明白我的意思。您应该查看 Python 的 pdb 模块。这是一个调试器,可让您单步调试代码,对解决此类问题非常有帮助。

【讨论】:

  • 非常感谢。没有意识到利率在哪里类变量。现在可以了。
猜你喜欢
  • 1970-01-01
  • 2013-03-06
  • 1970-01-01
  • 2022-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-22
  • 1970-01-01
相关资源
最近更新 更多