我有两个相关的 Django 模型。其中一个模型进行了昂贵的计算,__init__
如果没有不可接受的成本/风险,我无法转移到其他地方。
事实证明,并非在所有情况下都需要这些昂贵的计算,因此我引入了一个绕过它们的代理模型。但是,它们经常需要,因此将昂贵的用于代理是不切实际的。
所以,我的代码基本上是这样的:
class Person(models.Model):
def __init__(self, *args, **kw):
models.Model.__init__(self, *args, **kw)
do_some_really_expensive_things()
class LightweightPerson(Person):
class Meta:
proxy = True
def __init__(self, *args, **kw):
models.Model.__init__(self, *args, **kw)
class PersonFact(models.Model):
fact = models.TextField()
person = models.ForeignKey(Person)
这很好用——我的大部分代码查询都在Person
. 在代码不需要真正昂贵的东西的少数地方,它会查询LightweightPerson
,并且性能更好。
但是,我的一些代码从PersonFact
实例开始并访问person
每个PersonFact
. 此代码不需要真正昂贵的人员计算,并且这些昂贵计算对性能的影响是不可接受的。所以我希望能够在这种情况下实例化 aLightweightPerson
而不是 a 。Person
我想出的方法是添加一个ForeignKey
引用代理类的第二个,并使用相同的数据库列:
class PersonFact(models.Model):
fact = models.TextField()
person = models.ForeignKey(Person, db_column="person_id")
lightweight_person = models.ForeignKey(
LightweightPerson, db_column="person_id",
related_name="lightweight_personfact_set")
所以现在当我需要性能提升时,我的代码可以做这样的事情:
facts = PersonFact.objects.select_related(
"lightweight_person").all()
for fact in facts:
do_something_with(fact.lightweight_person)
这很好用!直到我尝试保存一个新的PersonFact
:
>>> fact = PersonFact(fact="I like cheese", person=some_guy_i_know)
>>> fact.save()
Traceback (most recent call last):
...
DatabaseError: column "person_id" specified more than once
:-(
有什么方法可以做到这一点,而无需对当前的代码进行大的可怕重构Person.__init__
?理想情况下,我要么能够在我的调用代码中发出“当person_fact.person
现在访问时,请实例化 aLightweightPerson
而不是 a ”的信号。Person
或者,或者,我希望能够PersonFact
在相同的数据库列上声明一个“代理相关字段”,但 Django 的内部知道只与数据库列交互一次。