2011-11-04 59 views
3

假设模型,如下所示:高效查询的Django的多对多额外字段通过

class GraphNode(models.Model): 
    name = models.CharField(...) 
    edges = models.ManyToManyField('self', through=Edge, 
            symmetrical=False) 

class Edge(models.Model): 
    source = models.ForeignKey(GraphNode, ...) 
    destination = models.ForeignKey(GraphNode, ...) 
    edge_type = models.CharField(...) 

我想回答这样的疑问:

与NODE_N一个节点开始,什么都是通过边缘型“foobar的”

连接的节点我希望能这样说:

results = GraphNode.objects.filter(source_set==node_n, 
            edges__edge_type='foobar') 

但是,该语法不起作用(边缘跳过通过表,所以没有'edge_type'字段)。也不对:

results = GraphNode.objects.filter(edge__source=node_n, 
            edge__edge_type='foobar') 

除非我删除了多对多字段声明!上面查询语法的工作点。

这是一个错误?有没有更好/最好的方法来查询ManyToMany通过表上的“额外的领域”,而不使用select_related?

回答

0

您的错误#1试图将Edge作为ManyToMany连接表使用。如果您使用via参数,它必须是第三个表格。关系代数中不可能通过两个表中的一个来做m2m。

其次,在这里你不需要很多。对于许多人来说,您无法对边缘中的多个节点设置限制。

另一个错误是,您使用GraphNode...(source_set=,您可以通过边缘过滤,但将其与节点进行比较。

只需删除多对多字段。

class Edge(models.Model): 
    source = models.ForeignKey(GraphNode, related_name='outcoming') 
    destination = models.ForeignKey(GraphNode, related_name='incoming') 
    edge_type = models.CharField(...) 

GraphNode.objects.filter(
    Q(outcoming__target=node_n) | # nodes that have edges that have node_n as target 
    Q(incoming__source=node_n) # the opposite 
) 
+0

我不知道我理解你说过的很多事情。什么是“通过参数”?而且,使用'self'和设置'through'参数来设置ManyToMany是完全正确的。我没有谈及限制边缘节点的数量,你为什么提到这一点? – slacy

+0

限制节点的数量 - 好吧,这是隐含的要求,不是吗?对不起,我误解了结构。这是一个有趣的设置。我需要尝试在我的机器上运行它。 –

相关问题