2012-05-31 108 views
3

如何在模型上創建動態字段?將動態字段添加到Django模型

假設我正在寫一個與股票市場相關的應用程序。我在某一天進行購買,之後我想根據今天的價格來檢查收益(或損失)。我有這樣一個模型:

class Purchase(models.Model): 
    ticker = models.CharField(max_length=5) 
    date = models.DateField() 
    price = models.DecimalField(max_digits=20, decimal_places=3) 
    quantity = models.IntegerField() 

我希望做的是定義一個模式是這樣的:

class PurchaseGain(Purchase): 
    gain = models.DecimalField(max_digits=20, decimal_places=3) 
    class Meta: 
    proxy = True 

,這樣我可以做到這一點:

todays_price = get_price_from_webservice(ticker) 
for p in PurchaseGain.objects.get_purchase_gain(todays_price): 
    print '%s bought on %s for a gain of %s' % (p.ticker, p.date, p.gain) 

其中p.gain是基於get_purchase_gain的輸入動態計算的。我不想僅僅使用模型構建字典,因爲我希望通過實例來傳遞這些信息並生成表單,保存更改等。

我試着創建一個派生的QuerySet,但這導致了循環依賴性,因爲Purchase需要了解QuerySet(通過自定義管理器)並且QuerySet返回了需要實例化PurchaseGain的迭代器,該派生自派生自採購。

我有什麼選擇?

謝謝, 克雷格

回答

2

創建代理類是什麼讓我感到困惑。通過給購買添加屬性,我能夠完成我想要的任務。

class PurchaseQuerySet(QuerySet): 
    def __init__(self, *args, **kwargs): 
    super(PurchaseQuerySet, self).__init__(*args, **kwargs) 
    self.todays_price = None 

    def get_with_todays_price(self, todays_price): 
    self.todays_price = todays_price 
    cloned = self.all() 
    cloned.todays_price = todays_price 
    return cloned 

    def iterator(self): 
    for p in super(PurchaseQuerySet, self).iterator(): 
     p.todays_price = self.todays_price 
     yield p 

class PurchaseManager(models.Manager): 
    def get_query_set(self): 
    return PurchaseQuerySet(self.model) 

    def __getattr__(self, name) 
    return getattr(self.get_query_set(), name) 

class Purchase(models.Model): 
    ticker = models.CharField(max_length=5) 
    date = models.DateField() 
    price = models.DecimalField(max_digits=20, decimal_places=3) 
    quantity = models.IntegerField() 

    objects = PurchaseManager() 

    @property 
    def gain(self): 
    return self.todays_price - self.price 

現在我可以這樣做:

for p in Purchase.objects.filter(ticker=ticker).get_with_todays_price(100): 
    print p 
    print p.gain 
3

爲什麼不增益()方法添加到您的模型?

class Purchase(models.Model): 
    ticker = models.CharField(max_length=5) 
    date = models.DateField() 
    price = models.DecimalField(max_digits=20, decimal_places=3) 
    quantity = models.IntegerField() 

    def gain(self, todays_price=None): 
     if not todays_price: 
      todays_price = get_price_from_webservice(self.ticker) 
     result_gain = todays_price - self.price 
     return result_gain 

那麼你幾乎可以做你想做的:

for p in Purchase.objects.all(): 
    print '%s bought on %s for a gain of %s' % (p.ticker, p.date, p.gain()) 
+2

你甚至可以使用'@ property'裝飾所以你可以稱其爲'p.gain'。 –

+0

謝謝。這會工作,但不會擴展。我可以爲單個股票交易者購買數百或數千次的交易。我正在尋找一種方法,可以預先計算並將它傳遞給查詢。雖然也許我只是想看看緩存遠程調用。我必須考慮這一點。 –

+0

我一醒來就不應該回復。我沒有這樣做的原因是,現在HTTP調用被硬編碼到我的模型中,這使得單元測試幾乎不可能。我想要一些可以依賴注入一個真正的HTTP客戶端或模擬測試的東西。這就是我喜歡上面提出的模型。 –

相關問題