python - 使用 Django MTI 找出子类型或将类型指定为字段?

标签 python django django-models

我正在使用多表继承 (MTI) 在 Django 中设置数据模型,如下所示:

class Metric(models.Model):
    account = models.ForeignKey(Account)
    date = models.DateField()
    value = models.FloatField()
    calculation_in_progress = models.BooleanField()
    type = models.CharField( max_length=20, choices= METRIC_TYPES ) # Appropriate?

    def calculate(self):
        # default calculation...

class WebMetric(Metric):
    url = models.URLField()

    def calculate(self):
        # web-specific calculation...

class TextMetric(Metric):
    text = models.TextField()

    def calculate(self):
        # text-specific calculation...

我的直觉是在基类中放置一个“类型”字段,如此处所示,这样我就可以分辨出任何 Metric 对象属于哪个子类。一直保持最新状态会有点麻烦,但有可能。但我需要这样做吗? django 有什么方法可以自动处理这个问题吗?

当我调用 Metric.objects.all() 时,返回的每个对象都是 Metric 的实例,而不是子类。因此,如果我调用 .calculate(),我永远不会得到子类的行为。

我可以在基类上编写一个函数来测试我是否可以将它转换为任何子类型,例如:

def determine_subtype(self):
    try:
        self.webmetric
        return WebMetric
    except WebMetric.DoesNotExist:
        pass
    # Repeat for every sub-class

但这看起来像是一堆重复的代码。而且它也不是可以包含在 SELECT 过滤器中的东西——只适用于 python 空间。

处理此问题的最佳方法是什么?

最佳答案

虽然它可能会冒犯某些人的敏感度,但解决此问题的唯一实用方法是在基类中放置一个字段或一个方法,说明每条记录到底是什么类型的对象。您描述的方法的问题在于,对于您正在处理的每个对象,它需要对每种类型的子类进行单独的数据库查询。在处理大型查询集时,这可能会变得非常慢。更好的方法是对 django 内容类型类使用 ForeignKey。

@Carl Meyer 在这里写了一个很好的解决方案:How do I access the child classes of an object in django without knowing the name of the child class?

单表继承可以帮助缓解这个问题,具体取决于它的实现方式。但目前 Django 不支持它:Single Table Inheritance in Django所以这不是一个有用的建议。

关于python - 使用 Django MTI 找出子类型或将类型指定为字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3990470/

相关文章:

django - Django 中如何发送电子邮件

django - 需要有关 Django ModelForm : How to filter ForeignKey/ManyToManyField? 的帮助

python - 通过 onetoone 模型字段属性过滤 django 查询集

python - 使用Pandas dataframe处理列表数据get loc错误

python - 在 Python 中自省(introspection)给定函数的嵌套(本地)函数

django - 模型表单集和日期字段

javascript - Django 模板中的 Vue.js

python - Django 查询集最佳实践

Python:循环从最后一项开始并以第一个结束

python - 使用Python获取字符的unicode代码点