2012-10-01 24 views
8

如果我的問題變得愚蠢,我很抱歉,但是我對Django比較陌生,我無法在任何地方找到答案。Django模型 - 分配id而不是對象

我有以下型號:

class BlackListEntry(models.Model): 
    user_banned = models.ForeignKey(auth.models.User,related_name="user_banned") 
    user_banning = models.ForeignKey(auth.models.User,related_name="user_banning") 

現在,當我嘗試創建這樣一個對象:

BlackListEntry.objects.create(user_banned=int(user_id),user_banning=int(banning_id)) 

,我收到了以下錯誤:

Cannot assign "1": "BlackListEntry.user_banned" must be a "User" instance. 

中當然,如果我用這樣的東西代替它:

user_banned = User.objects.get(pk=user_id) 
user_banning = User.objects.get(pk=banning_id) 
BlackListEntry.objects.create(user_banned=user_banned,user_banning=user_banning) 

一切工作正常。問題是:

我的解決方案是否觸及數據庫以檢索兩個用戶,如果是,是否可以避免它,只是傳遞ID?

回答

10

您的問題的答案是:是的。

Django會觸發數據庫(至少)3次,2檢索兩個用戶對象,第三個用於提交您想要的信息。這將導致絕對不必要的開銷。

試試看:

BlackListEntry.objects.create(user_banned_id=int(user_id),user_banning_id=int(banning_id)) 

這些是由Django的ORM生成的FK字段的默認名稱模式。這樣您可以直接設置信息並避免查詢。

如果您想查詢已保存的BlackListEntry對象,你可以用雙下劃線導航屬性,像這樣:

BlackListEntry.objects.filter(user_banned__id=int(user_id),user_banning__id=int(banning_id)) 

這是你如何在Django的查詢集訪問性能。用雙下劃線。然後你可以比較屬性的值。

雖然非常相似,但它們的工作完全不同。第一個直接設置一個屬性,而第二個設置是由django解析的,它將其分割爲'__',並以正確的方式查詢數據庫,第二部分是屬性的名稱。

您總是可以將user_banneduser_banning與實際的用戶對象(而不是其ID)進行比較。但是,如果你還沒有與你一起擁有這些物品,那就沒有用處。

希望它有幫助。

+0

這給了我: 'user_banning__id'是此函數的一個無效關鍵字參數 –

+0

對不起,我剛剛意識到您正在創建對象。所以,你需要使用一個下劃線來訪問。我將編輯我的答案以解釋爲什麼。 – Francisco

+0

謝謝,現在它工作。我會給你加+1,但我還不能這麼做。 –

0

我相信,當你獲取用戶,它會擊中分貝......

爲了避免它,你就必須編寫原始SQL使用這裏介紹的方法做了更新:​​

https://docs.djangoproject.com/en/dev/topics/db/sql/

如果你決定走這條路要記住,你有責任保護自己免受SQL注入攻擊。

另一種選擇是緩存user_banned和user_banning對象。

但很有可能,只需抓住用戶並創建BlackListEntry不會導致任何明顯的性能問題。緩存或執行原始sql只會帶來一點好處。在這成爲問題之前,您可能會遇到其他問題。