2011-11-04 58 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

限制節點的數量 - 好吧,這是隱含的要求,不是嗎?對不起,我誤解了結構。這是一個有趣的設置。我需要嘗試在我的機器上運行它。 –

相關問題