向Django模型添加动态字段

时间:2012-05-31 05:00:27

标签: python django django-models model

如何在模型上创建动态字段?

假设我正在撰写与股票市场相关的应用程序。我在一天购买,之后某个时候我想根据今天的价格检查收益(或损失)。我有一个这样的模型:

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,它是从Purchase派生的

我有哪些选择?

谢谢, 克雷格

2 个答案:

答案 0 :(得分:3)

为什么不在模型中添加 gain()方法?

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

答案 1 :(得分: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