动态添加属性到 Django 模型

Dynamically add properties to Django model

目前我有以下Django模型

class TestUser(models.Model):
    name = models.CharField(max_length=250)
    email = models.CharField(max_length=250)
    ...

    class Meta:
        db_table = 'temp_user'

我有以下方法。

def print_name(self):
    return self.name

我想将此方法作为 属性 添加到 TempUser 模型。我知道这可以通过将方法放在 TempUser class 和用户 @property 中来完成。但是我想动态地做。

我从 python shell.

试过这个
In [10]: TempUser.print_name = property(print_name)

In [11]: TempUser.print_name
Out[11]: <property at 0x7efc374e7c58>

In [12]: user = TempUser.objects.get(pk=1)

In [13]: user.print_name
Out[13]: u'Test User'

但是一旦我退出 shell,我就会松开 属性。有什么方法可以永久添加属性。

But once I exit the shell, I loose the property. Is there any way to add the property permanently.

不,不是通过您在 运行 时设置的属性。与 Django 模型实例关联的数据通过数据库持久化。 持久化 数据的唯一选择是在数据库中创建一个用于存储信息的字段。如果您想保留 class 上可用的方法,请编辑源代码。

您也表示希望在 运行 时动态执行此操作。但是,这样做的好处充其量是可疑的,并且可能对您的代码库有害。很难想象一个可证明的用例,它可以解决一个没有更好解决方案的实际问题。几乎可以肯定有更好的方法来实现您的目标。如果您的目标是保持代码干爽,请考虑其他模式,例如从抽象模型继承。

您可以在您的模型 class 上实现常规属性(使用 @property 方法装饰器),这些属性可以获取现有字段并查看相关模型字段以即时组合信息,但是它仍然没有保存在数据库中...

例如,如果您的模型具有 start_timeend_time,您可以添加 total_time 属性 而不必为其创建字段.

class MyModel(models.Model):
    start_time = models.DateTimeField()
    end_time = models.DateTimeField()

    @property
    def total_time(self):
        return self.end_time - self.start_time

但是,这样做将不允许您对此进行查询 属性。例如 MyModel.objects.filter(total_time__lt=delta) 单独使用 属性 是不可能的。

您拥有的其他一些选项包括 annotation and aggregation,它可以在 运行 时动态完成,并使您能够查询数据库。

使用与上面相同的示例,而不是使用 @property 可以以类似的方式注释查询集,这也允许您在此 'virtual field' 上查询数据库,甚至传递带注释的查询集大约。您甚至可以进行算术和聚合,例如总和、平均值等...

from django.db.models import F, ExpressionWrapper, fields

duration = ExpressionWrapper(F('end_time') - F('start_time'), output_field=fields.DurationField())

qs = MyModel.objects.annotate(duration=duration)
# query for objects with a delta of more than five minutes
results = qs.filter(duration__gt=five_minutes)

另见 Query expressions

简而言之:不,如果可以的话,这几乎肯定是个坏主意。坚持既定的做事方法。 Django 是一个非常自以为是的框架,它是专门为你做事的'the django way'。违背规律只会伤害自己。