2015-06-25 64 views
0

原來的問題造成相當尷尬的循環模型引用:錯誤GROUP BY字段在Django註釋查詢

# A -> B -> A 

class A: 
    b = models.ForeignKey('B', null=True, blank=True) 

class B: 
    a = models.ForeignKey('A') 

現在,當我試圖詮釋查詢,它總是使用GROUP BY從LEFT OUTER一個的ID JOIN(T3.id在下面的示例中)而不是a.id

例子:

A.objects.select_related('b', 'b__a').annotate(reviews=Count('reviews')) 

生成的SQL:

SELECT 
    `a`.`id`, 
    `b`.`id`, 
    T3.`id`, 
FROM 
    `a` 
     LEFT OUTER JOIN 
    `b` ON (`a`.`b_id` = `b`.`id`) 
     LEFT OUTER JOIN 
    `a` T3 ON (`b`.`a_id` = T3.`id`) 
WHERE 
    `a`.`id` IN (1, 2, 3, 4, 5) 
GROUP BY T3.`id` 
ORDER BY NULL; 

我知道我可以做接下來的事情就:

  1. 更改模式不做循環引用(可惜不能做那現在)
  2. 可以使用.extra()而不是註釋(我會盡量避免吧)
  3. 刪除.select_related()調用(不能做的,由於性能問題)

UPD:使用GROUP BY T3.id將排除結果,其中AB = =無

對我來說最好的解決方案就是在GROUP BY子句中指定正確的字段,但我不知道如何。可能嗎?有沒有其他方法可以解決這個問題?謝謝。

+0

的問題不是'T3 ==了','從一個爲T3'?不知道你想在這裏實現什麼.. – mccc

+0

使用GROUP BY T3.id排除了a.b == None的結果,同時它不是預期的。 – ZAN

+0

至於我想達到的目標 - 一個模型可以通過B具有父對象。我知道這不是最好的方法,但它是一種模型演變。 – ZAN

回答

0

開業Django的編譯器:

def collapse_group_by(self, expressions, having): 
    # If the DB can group by primary key, then group by the primary key of 
    # query's main model. Note that for PostgreSQL the GROUP BY clause must 
    # include the primary key of every table, but for MySQL it is enough to 
    # have the main table's primary key. Currently only the MySQL form is 
    # implemented. 
    # MySQLism: however, columns in HAVING clause must be added to the 
    # GROUP BY. 
    if self.connection.features.allows_group_by_pk: 
     # The logic here is: if the main model's primary key is in the 
     # query, then set new_expressions to that field. If that happens, 
     # then also add having expressions to group by. 
     pk = None 
     for expr in expressions: 
      if (expr.output_field.primary_key and 
        getattr(expr.output_field, 'model') == self.query.model): 
       pk = expr 
       # HERE BREAKPOINT REQUIRED 
     if pk: 
      expressions = [pk] + [expr for expr in expressions if expr in having] 
    return expressions 

所以,collapse_group_by功能不會停止尋找PK即使它已經發現,這就是爲什麼通過分組由T3.id做的,而不是a.id(因此我缺少結果)。 爲了解決這個問題,for循環中需要斷點(在註釋中標記)。

UPD:已經固定在Django 1.8.2版本https://code.djangoproject.com/ticket/24748