2010-11-11 84 views
0

我在我的一個模型上動態地覆蓋了Django的get_query_set函數。我這樣做是爲了強制過濾由Model.objects.all/filter/get通過「場景」值返回的原始查詢集,使用裝飾器。這裏的裝飾器的功能:Django的get_query_set覆蓋正在被緩存

# Get the base QuerySet for these models before we modify their 
# QuerySet managers. This prevents infinite recursion since the 
# get_query_set function doesn't rely on itself to get this base QuerySet. 
all_income_objects = Income.objects.all() 

# Figure out what scenario the user is using. 
current_scenario = Scenario.objects.get(user=request.user, selected=True) 

# Modify the imported income class to filter based on the current scenario. 
Expense.objects.get_query_set = lambda: all_expense_objects.filter(scenario=current_scenario) 

# Call the method that was initially supposed to 
# be executed before we were so rudely interrupted. 
return view(request, **arguments) 

我這樣做幹起來的代碼,以便我所有的查詢不散佈與額外的過濾器。但是,如果場景更改,則不會返回對象。如果我殺死了我服務器上的所有python進程,則會出現新選擇方案的對象。我在考慮緩存修改後的類,然後當情景發生變化時,它會應用另一個永遠不會有意義的過濾器,因爲對象一次只能有一個場景。

這不是基於用戶的過濾器的問題,因爲用戶永遠不會更改我的會話。乘客是否做了一些愚蠢的事情來阻止請求之間的類對象?我應該在這個奇怪的設計模式上放肆,並且只是在每個視圖的基礎上實現這些過濾器? DRYing過濾器必須有一個最佳實踐,適用於基於動態的許多視圖,如當前用戶。

+0

我看不到裝飾者在哪裏? – Unode 2010-11-11 19:15:59

回答

0

如何爲模型創建Manager對象,該模型將用戶作爲參數進行過濾。我的是DRY W/Django的查詢集的理解是使用模型管理器

#### view code: 
def some_view(request): 
    expenses = Expense.objects.filter_by_cur_scenario(request.user) 

    # add additional filters here, or add to manager via more params 
    expenses = expenses.filter(something_else=True) 

#### models code: 
class ExpenseManager(models.Manager): 
    def filter_by_cur_scenario(self, user): 
     current_scenario = Scenario.objects.get(user=request.user, selected=True) 
     return self.filter(scenario=current_scenario) 

class Expense(models.Model): 
    objects = ExpenseManager() 

此外,在管理器(它可以適用於覆蓋get_query_set)一個快速的警告:外國的關係不會考慮在做任何過濾這個級別。例如,您重寫MyObject.objects.filter()方法以始終過濾掉已刪除的行;具有外鍵的模型不會使用該過濾器功能(至少從我的理解 - 如果我錯了,請有人糾正我)。

0

我希望能夠實現這種實現,而不必在其他視圖中編寫任何代碼。實質上,在導入類之後,我想對其進行修改,以便無論使用Expense.objects.get/filter/all引用它,它都已被過濾。因此,任何其他觀點都不需要實施;它是完全透明的。而且,即使在我將其用作ForeignKey的情況下,當使用上述的Expense.objects.get/filter/all檢索對象時,也會對其進行過濾。