目前我有以下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
类和用户@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'
但是一旦我退出贝壳,我就松开了房产。有没有办法永久添加属性。
答案 0 :(得分:2)
但是一旦我退出贝壳,我就松开了房产。有没有办法永久添加属性。
不,不是通过您在运行时设置的属性。与Django模型实例相关的数据通过数据库保留。 持久数据的唯一选择是在数据库中创建用于存储信息的字段。如果要保留类上可用的方法,请编辑源代码。
您已表达了在运行时动态执行此操作的愿望。但是,这样做的好处至多是可疑的,并且可能对您的代码库造成危害。很难想象一个可证明的用例,它解决了一个尚未有更好解决方案的真正问题。几乎可以肯定有更好的方法来实现目标。如果您的目标是保持代码干燥,请考虑其他模式,例如继承抽象模型。
您可以在模型类上实现常规属性(使用@property
方法装饰器),可以获取现有字段并查看相关模型字段以即时组合信息,但它仍然不会保留在数据库......
例如,如果您的模型具有start_time
和end_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
,可以以类似的方式注释查询集,这也允许您在此“虚拟字段”上查询数据库,甚至传递带注释的查询集。你甚至可以进行算术和聚合,如总和,平均等......
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)
简而言之:不,如果可以的话,这几乎肯定是一个坏主意。坚持既定的做事方法。 Django是一个非常固执己见的框架,它是专为你做'django方式'而设计的。你可能只会因为违背粮食而伤害自己。