Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 向Django模型添加动态字段_Python_Django_Django Models_Model - Fatal编程技术网

Python 向Django模型添加动态字段

Python 向Django模型添加动态字段,python,django,django-models,model,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) quant

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

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

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
我想做的是定义一个类似这样的模型:

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是基于获取_purchase _gain的输入动态计算的。我希望使用一个模型,而不仅仅是动态地构建字典,因为我希望传递这个模型,并从实例生成表单、保存更改等

我尝试创建一个派生的QuerySet,但这导致了一个循环依赖关系,因为Purchase需要了解QuerySet(通过自定义管理器),QuerySet返回一个迭代器,需要实例化PurchaseGain,它是从Purchase派生的

我有什么选择

谢谢, Craig

为什么不在模型中添加一个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())

创建代理类让我很困惑。只需为购买添加属性,我就能实现我想要的

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

您甚至可以使用
@property
装饰器,因此您可以将其称为
p.gain
。谢谢。这是可行的,但无法扩展。我可能有数百或数千购买一个单一的股票。我正在寻找一种可以预计算并将其传递给查询的方法,尽管我可能只需要看看如何缓存远程调用。我得想一想,我不应该一醒来就做出反应。我没有这样做的原因是,现在HTTP调用被硬编码到我的模型中,这使得单元测试几乎不可能。我想要的东西,我可以依赖注入一个真正的HTTP客户端或模拟一个测试。这就是我喜欢上面提出的模型的原因。好的,我在增益方法中添加了一个可选的“新价格”,这将允许测试。我同意你上面的评论,如果你关心性能,你应该以某种方式研究缓存。您仍然可以将缓存检索放在gain()方法中。