如何通过hasattr确定子类在django的orm中触发db查询?

时间:2012-07-27 20:00:29

标签: django django-models django-orm

例如,我正在为具有子类ConceptNode和DerivedNode的类Node使用多表继承。为了确定我正在处理的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如何被翻译成数据库查询。

此外,如果任何人都可以建议一种更有效的方法来处理这种情况(尤其是从查询计数的角度来看),那也很棒!

编辑:要转储执行的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 个答案:

答案 0 :(得分:0)

您有两个简单节点查找实例(LIMIT 1查询),因为您多次以列表形式访问查询集。

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

触发两个查询,而:

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

触发一个。这一开始看起来有点奇怪,但关键是要记住在访问Node.objects.all()之前不会对class Node(models.Model): pass class ConceptNode(Node): pass 进行评估(不进行任何查询)。

至于为什么单个对象查找运行两个查询,您使用的是multi-table inheritance。如果你的模型中有这个:

ConceptNode

Django将创建两个表,其中Node行具有父abstract = True

您可能正在寻找的是abstract base class,它允许您在多个类之间共享方法和属性,而每个类只使用一个表。只需将class Node(models.Model): class Meta: abstract = True 添加到父类meta:

{{1}}

最后请注意,这两个查询都应该几乎没有时间,所以我不会太担心它。