2

1対多の関係を表す2つのモデルがあります。InterestRateCurveオブジェクトには、多くのInterestRateオブジェクトを含めることができます。問題は、各曲線が1つのレートを持つ2つの曲線を作成する関数がある場合、2番目の曲線のレートが最初の曲線のレートを上書きすることです。したがって、データベースには、曲線用に2行、レート用に1行が含まれることになります。1つのカーブと1つのレートを保存するプログラムを実行してから、別のカーブをレートで保存する別のプログラムを実行すると、すべて問題ありません。

Python2.7とDjango1.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()

この実行により、1つの曲線と1つのレートが節約されます。

別の実行で私は実行します:

        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()

これにより、2つの曲線が保存されますが、保存されるレートは1つだけです。2番目のレートは、以前に保存された最初のレートを上書きしているようです。

4

1 に答える 1

1

問題は、rates = []のクラス変数としての指定ですInterestRateCurve。この定義により、のすべてのオブジェクトがInterestRateCurve同じレートのリストにアクセスします。

例で最初の曲線とレートを作成した後、作成さInterestRateCurve.ratesれた1つのレートが含まれます。次に、2番目の曲線を作成して保存します。実行され、ブランチInterestRateCurve.save()にジャンプして、次のことを行います。except

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

self.rates(= InterestRateCurve.rates)にはあなたのファーストレートが含まれていることを覚えていますか?ループは、このレートの外部キーを2番目のカーブに設定し、それを保存します。これで、最初の曲線には関連するレートがなくなりました。最初のカーブのレートは、2番目のカーブに属します。

その後、最初のレートとまったく同じ属性を持つ2番目のレートを作成します。InterestRateモデルで指定したので:

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

...まったく同じ属性を持つレートは1つだけです。古いものが削除されたのか、新しいものが保存されなかったのかわかりません。ただし、結果として、データベースには2番目の曲線に属するレートオブジェクトが1つだけあります。

私が何を意味するのか理解していただければ幸いです。Pythonのpdbモジュールを見る必要があります。これは、コードをステップ実行できるデバッガーであり、このような問題に非常に役立ちます。

于 2012-11-15T19:03:22.060 に答える