0

たとえば、サブクラスConceptNodeとDerivedNodeを持つクラスNodeにマルチテーブル継承を使用しています。処理しているノードのタイプを判別し、関数呼び出しを適切なサブクラスに配布するには、次のようにhasattrを呼び出さなければならないことがよくあります。

test_node = Node.objects.all()[0]

if hasattr( test_node, "conceptnode"):
    test_node.conceptnode.myFunction()
elif hasattr( test_node, "derivednode"):
    test_node.derivednode.myFunction()
else:
   raise Exception("Not a valid type.")

これにより、複数のデータベースクエリが発生し、作成した一部の関数の速度が大幅に低下することに気付きました。

クエリの数を減らさないtry...catchを使用して別のアプローチを試しました。

test_node = Node.objects.all()[0]

try:
    test_node.conceptnode.myFunction()
except ObjectDoesNotExist:
    test_node.derivednode.myFunction()

私の主な質問は、djangoがここで実行するクエリをどのように決定するかということです。hasattrがどのようにdbクエリに変換されているのかわかりません。

また、誰かがこれを処理するためのより効率的な方法を提案できれば(特にクエリ数の観点から)、それも素晴らしいことです!

編集:実行されたsqliteクエリをダンプするために、私は次のことを行いました:

from django.db import connection
from django import db
db.reset_queries()
hasattr(nds[0],'conceptnode')
hasattr(nds[0],'derivednode')
connection.queries

そして、私は次の結果を得ました:

{'sql': u'SELECT "nodes_node"."id", "nodes_node"."name", "nodes_node"."description", "nodes_node"."node_tree_id", "nodes_node"."unique_name", "nodes_node"."last_updated_timestamp", "nodes_node"."order", "nodes_node"."data_json", "nodes_node"."data_json_synchronized" FROM "nodes_node" LIMIT 1',  'time': '0.001'}
{'sql': u'SELECT "nodes_node"."id", "nodes_node"."name", "nodes_node"."description", "nodes_node"."node_tree_id", "nodes_node"."unique_name", "nodes_node"."last_updated_timestamp", "nodes_node"."order", "nodes_node"."data_json", "nodes_node"."data_json_synchronized", "nodes_conceptnode"."node_ptr_id", "nodes_conceptnode"."node_parent_id" FROM "nodes_conceptnode" INNER JOIN "nodes_node" ON ("nodes_conceptnode"."node_ptr_id" = "nodes_node"."id") WHERE "nodes_conceptnode"."node_ptr_id" = 1 ',  'time': '0.000'}
{'sql': u'SELECT "nodes_node"."id", "nodes_node"."name", "nodes_node"."description", "nodes_node"."node_tree_id", "nodes_node"."unique_name", "nodes_node"."last_updated_timestamp", "nodes_node"."order", "nodes_node"."data_json", "nodes_node"."data_json_synchronized" FROM "nodes_node" LIMIT 1',  'time': '0.001'}
{'sql': u'SELECT "nodes_node"."id", "nodes_node"."name", "nodes_node"."description", "nodes_node"."node_tree_id", "nodes_node"."unique_name", "nodes_node"."last_updated_timestamp", "nodes_node"."order", "nodes_node"."data_json", "nodes_node"."data_json_synchronized", "nodes_derivednode"."node_ptr_id", "nodes_derivednode"."node_source_id", "nodes_derivednode"."node_target_id" FROM "nodes_derivednode" INNER JOIN "nodes_node" ON ("nodes_derivednode"."node_ptr_id" = "nodes_node"."id") WHERE "nodes_derivednode"."node_ptr_id" = 1 ',  'time': '0.000'}

これらの1番目と3番目は、元のノードオブジェクトをフェッチしています。

4

1 に答える 1

0

LIMIT 1クエリセットにリストとして複数回アクセスしているため、単純なノードルックアップ(クエリ)のインスタンスが2つあります。

nodes = Node.objects.all()
nodes[0]
nodes[0]

2つのクエリをトリガーしますが、次のようになります。

node = Node.objects.all()[0]
node
node

1つをトリガーします。これは最初は少し奇妙に思えるかもしれませんが、重要なのは、Node.objects.all()アクセスするまで評価されない(クエリが行われない)ことを覚えておくことです。

単一オブジェクトルックアップが2つのクエリを実行する理由については、マルチテーブル継承を使用しています。モデルにこれがある場合:

class Node(models.Model):
    pass

class ConceptNode(Node):
    pass

Djangoは2つのテーブルを作成し、ConceptNode行には親がありNodeます。

おそらく探しているのは抽象基本クラスです。これにより、それぞれに1つのテーブルを使用するだけで、複数のクラス間でメソッドとプロパティを共有できます。abstract = True親クラスのメタに追加するだけです。

class Node(models.Model):
    class Meta:
        abstract = True

最後に、これらのクエリはどちらもほとんど時間がかからないはずなので、あまり心配する必要はありません。

于 2012-08-01T20:35:39.200 に答える