【问题标题】:Django Model - Mix model fields and instance attributes in classDjango Model - 在类中混合模型字段和实例属性
【发布时间】:2021-11-06 21:08:51
【问题描述】:

不确定我是否走错了路,但我想在我的 Django 模型中使用某种临时运行时变量/字段。目前我有这个:

class BioChemicalProperties(models.Model):
    mw = models.FloatField(blank=True, null=True)
    iep = models.FloatField(blank=True, null=True)
    exco = models.FloatField(blank=True, null=True)
    molar_exco = models.FloatField(blank=True, null=True)
    e01 = models.FloatField(blank=True, null=True)

    def get_protein(self):
        aa_seq = self.ab.get_lc_protein()
        aa_seq += self.ab.get_hc_protein()
        return aa_seq

    def calc_mw(self, aa_seq=None):
        if not aa_seq:
            aa_seq = self.get_protein()
        analysed_seq = ProteinAnalysis(aa_seq)
        self.mw = analysed_seq.molecular_weight() + 18.015

    def calc_exco(self, aa_seq=None):
        if not aa_seq:
            aa_seq = self.get_protein()
        analysed_seq = ProteinAnalysis(aa_seq)
        self.exco = analysed_seq.molar_extinction_coefficient()[1]
    
    #...more methods here...

    def calc_all_bioprops(self, aa_seq=None):
        if not aa_seq:
            aa_seq = self.get_protein()
        self.calc_mw(aa_seq)
        self.calc_iep(aa_seq)
        self.calc_molexco(aa_seq)
        self.calc_e01(aa_seq)

aa_seq 变量是一个临时值,不应存储在数据库中。尽管如此,当要使用多种方法时,为了不重新计算每种方法的值,我想有选择地将其作为参数提供。我看到在每个方法中将aa_seq 作为参数是多余的,也不是面向对象的。现在我想知道将它存储为类属性是否是一个好主意(并且可能),例如:

class BioChemicalProperties(models.Model):
    mw = models.FloatField(blank=True, null=True)
    iep = models.FloatField(blank=True, null=True)
    exco = models.FloatField(blank=True, null=True)
    molar_exco = models.FloatField(blank=True, null=True)
    e01 = models.FloatField(blank=True, null=True)
    aa_seq = ""

    def calc_mw(self):
        if not self.aa_seq:
            self.aa_seq = self.get_protein()
        analysed_seq = ProteinAnalysis(self.aa_seq)
        self.mw = analysed_seq.molecular_weight() + 18.015


但是,我还没有发现任何类似的模型字段和非模型字段混合的例子......这是有原因的吗?

【问题讨论】:

    标签: python django django-models django-queryset


    【解决方案1】:

    你的想法不错,但你的命名法很混乱。

    将它存储为实例属性绝对没有错。这不是一个领域,它在模型上是巧合。模型只是类的特例。

    Here 是在 Django 文档本身的 Model 子类上定义的非字段属性示例。

    【讨论】:

    • 感谢您的回答。我实现了它,它确实按预期工作。
    • IMO 这是有效的(我也赞成),但通常非字段属性用于常量之类的东西(如示例中的选择)。通过这种方法,可以将值设置为其他值,而不是使用propertycached_property(没有设置器)确保它始终是一个计算字段。这也不需要不断检查这个值是否已经计算出来,所以一堆if not self.aa_seq: self.aa_seq = calculate()
    • @BrianD 我完全不同意你的观点。我经常用作非字段属性的非常量事物的示例是管理器实例、字段跟踪器实例、临时变量、选项类等等。
    【解决方案2】:

    看起来cached_property 可以做到:

    from django.utils.functional import cached_property
    
    
    class BioChemicalProperties(models.Model):
        ...
        @cached_property
        def aa_seq(self):
            return self.ab.get_lc_protein() + self.ab.get_hc_protein()
    

    然后您可以像现在一样使用self.aa_seq,并且您可以删除if not aa_seq 检查,因为它不再需要了。此外,这将在实例的生命周期内缓存 aa_seq 的计算值,而不会将任何内容存储到数据库中。

    【讨论】:

    • 嗨@BrianD,感谢您的建议。虽然最初使用实例属性的简单方法似乎已经成功了,但 cached_property 对我来说是新的,对于其他用例来说,它看起来像是一种有趣的方法!
    • 一切顺利!我赞成@Adam Barnes 的答案,但请记住,使用这种方法,您必须始终检查aa_seq 是否已经计算(if not aa.seq)。也可以将其设置为实例之外的另一个值,这可能会引入您不期望的行为(如instance.aa_seq = somerandomvalue)。但取决于你
    猜你喜欢
    • 2013-10-18
    • 2014-11-23
    • 1970-01-01
    • 1970-01-01
    • 2011-06-06
    • 2014-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多