参考模型层中的相关模型字段

Posted

技术标签:

【中文标题】参考模型层中的相关模型字段【英文标题】:Refer related model field in model layer 【发布时间】:2019-09-14 10:53:29 【问题描述】:

我尝试在 django 模型层的模型“基础”中引用模型“现货”的“现货价格”,我该如何管理?

我设计了 view.py 来自动渲染模板。所以我无法修改任何 view.py 来选择像“models.B.objects.get().field”这样的数据。

还有,str设置为表示日期,所以,在django后台管理中,'spot'字段显示会是'date'格式,怎么改成'spot_price' ?

模型现货

class Spot(models.Model):
    date = models.DateField(primary_key=True)
    spot_price = models.FloatField(blank=True, null=True)

    def __str__(self):
        return str(self.date) if self.date else ''

需要按日期引用模型Spot的spot_price,因为日期是唯一的但spot_price不是

class Basis(models.Model):
    date = models.DateField(primary_key=True)
    major_future_contract_close_price = models.FloatField(blank=True)
    spot = models.OneToOneField(Spot, on_delete=models.CASCADE)
    basis = models.FloatField(default=calculate_basis)

    def __str__(self):
        return str(self.date) if self.date else ''

    def calculate_basis(self):
        return abs(self.major_future_contract_close_price - 
        self.spot.spot_price)

我预计 Basis.query.data 会喜欢“日期:2019-04-25,major_future_contract_close_price:100.0,现货:96.5,基础:3.5”

【问题讨论】:

您想在Basis 中仅为OneToOneField 更改Spot str 吗? calculate_basis 需要参考spot_price 吗? 没错,我在这个Basis模型中只需要spot_price,而在其他模型中,我更喜欢date作为str。 calculate_basis 需要 spot_price 模型中的 Spot 字段。 calculate_basis 在同一 date 中同时引用 spot_pricemajor_future_contract_close_price 【参考方案1】:

你不能默认使用类方法,因为它需要self,当你还在创建对象时,它并不存在。

如果您需要将其存储在字段(数据库)中,override default save() method 或在创建对象后使用 signals 修改 basis 字段。另请注意,每次close_pricespot_price 更改时,您都必须重新计算基,因为该值只是写入数据库中。

可能更好的解决方案是使用@property,因此对于将使用您的模型的任何人来说,它看起来像一个字段,但它会根据当前数据动态计算值。

例如,我将覆盖 save() 来计算 basis 字段。我将其设置为editable=False,这意味着默认情况下它不会出现在表单中(并且您将无法在管理员中看到它!)。如果您只想查看值,则可以安全地删除该部分。 另外我添加了basis_as_property 属性。

class Basis(models.Model):
    date = models.DateField(primary_key=True)
    major_future_contract_close_price = models.FloatField(blank=True)
    spot = models.OneToOneField(Spot, on_delete=models.CASCADE)
    basis = models.FloatField(editable=False, blank=True)

    @property
    def basis_as_property(self):
        return '%s' % (self.calculate_basis())

    def __str__(self):
        return str(self.date) if self.date else ''

    def save(self, *args, **kwargs):
        if not self.basis:
            self.basis = self.calculate_basis()
        super(Basis, self).save(*args, **kwargs)

    def calculate_basis(self):
        return abs(self.major_future_contract_close_price - self.spot.spot_price)

至于Spot str repr,我认为不可能根据引用的位置进行更改。如果你想使用spot_price,你可以使用:return str(self.spot_price) if self.spot_price else str(self.date)

【讨论】:

对不起,我还不熟悉***,以为您可能没有看到我的回复。我只在这个Basis 模型中使用spot_price,而在其他模型中,我更喜欢date 作为str。 calculate_basis 方法要求spot_pricemajor_future_contract_close_price 具有相同的date

以上是关于参考模型层中的相关模型字段的主要内容,如果未能解决你的问题,请参考以下文章

模型层中模型的基本了解

如何在 OBIEE 12c 中查看业务模型和映射层中的数据?

视图层中的 DTO 或域模型对象?

Django模型字段实际上是对相关模型中的字段的引用

根据 DTO、实体模型或其他东西验证服务层中的数据?

Django 仅序列化一个字段而不是相关字段中的整个模型(只读)