関連する 2 つの Django モデルがあります。モデルの 1 つは高価な計算を行っているため、__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
代わりにクエリを実行し、パフォーマンスを向上させます。
ただし、私のコードの一部はインスタンスから始まり、関連するfor eachPersonFact
にアクセスします。このコードは、非常にコストのかかる個人計算を必要とせず、それらのコストのかかる計算によるパフォーマンスへの影響は容認できません。したがって、このコンテキストで a の代わりに aをインスタンス化できるようにしたいと思います。person
PersonFact
LightweightPerson
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
理想的には、「今アクセスするときは、呼び出しコードで a のLightweightPerson
代わりに aをインスタンス化してください」というシグナルを送ることができます。Person
または、代わりに、同じデータベース列をシャドウする「プロキシ関連フィールド」を宣言できるようにしたいのですPersonFact
が、Django の内部はデータベース列と一度だけ対話することを知っています。