2011-02-18 88 views
3

如何防止Django出於測試目的在初始查詢過程中自動獲取未在select_related()調用中指定的相關表?Django - 阻止自動獲取相關表

我有一個很大的應用程序,我大量使用 select_related()在每個原始 查詢期間引入相關模型數據。所有select_related()調用都用於指定特定的相關模型,而不是依靠默認的,例如, select_related(「富」,「酒吧」,「foo__bar」)

隨着應用的不斷壯大,select_related電話還沒有完全 跟上,留下了許多場景,其中的Django愉快 和親切那張跑開去該數據庫提取相關模型 行。這顯着增加了數據庫命中的數量,這顯然不需要。

我通過檢查使用django.db.connection.queries集合生成的查詢 ,但在某些 未解決的情況下,我已成功跟蹤這些查詢。

我試圖找到Django的代碼中的相應補丁的位置,以提高在這種情況下的 例外,使得跟蹤更加容易,但往往 迷失在代碼中。

謝謝。

+0

對於開發,我建議你使用Django調試工具欄。它顯示查詢在數據庫中執行的詳細信息(如查詢總數和每個執行的查詢)https://github.com/robhudson/django-debug-toolbar – FallenAngel 2011-02-18 15:31:06

+0

@FallenAngel,謝謝你的提示 - 我不會用調試工具欄之前,它是非常有用的。 – 2011-03-13 19:51:31

回答

1

經過一番更多的挖掘,我發現在代碼中的位置來做到這一點。

問題中的文件是Django的/ DB /模型/場/ related.py

你需要兩行加入到這個文件。

找到類「SingleRelatedObjectDescriptor」。您需要更改的功能__get __()如下:進一步

def __get__(self, instance, instance_type=None): 
    if instance is None: 
     return self 
    try: 
     return getattr(instance, self.cache_name) 
    except AttributeError: 
     raise Exception("Automated Database Fetch on %s.%s" % (instance._meta.object_name, self.related.get_accessor_name())) 
     # leave the old code here for when you revert! 

同樣,在課堂上 「ReverseSingleRelatedObjectDescriptor」 下的代碼,你需要再次改變__get __()來:

def __get__(self, instance, instance_type=None): 
    if instance is None: 
     return self 

    cache_name = self.field.get_cache_name() 
    try: 
     return getattr(instance, cache_name) 
    except AttributeError: 
     raise Exception("Automated Database Fetch on %s.%s" % (instance._meta.object_name, self.field.name)) 
     # BEWARE: % parameters are different to previous class 
     # leave old code here for when you revert 

一旦你已經完成了這一步,您會發現Django每次執行自動數據庫查找時都會引發異常。這在第一次啓動時非常煩人,但它會幫助您追蹤那些討厭的數據庫查找。顯然,當你找到它們時,最好將數據庫代碼恢復到正常狀態。我只會建議在調試/性能調查階段使用它,而不是在現場生產代碼中使用!

0

那麼,你在問怎麼停止一個方法來做它專門設計的方法呢?我不明白你爲什麼想這麼做。

但是,有關select_related的一件事情是,它不會自動遵循定義爲null=True的關係。所以如果你現在可以設置你的FK,那麼關係就不會被遵循。