2016-02-29 59 views
2

我正在爲使用自定義權限處理的現有系統開發REST API。我試圖使用Django REST框架中的內置泛型,但我遇到了使用我的自定義權限過濾列表視圖的麻煩。我當前視圖的一個例子是:使用自定義函數過濾Django查詢集

class WidgetList(generics.ListCreateAPIView): 
    permission_classes = (permissions.IsAuthenticated,) 
    model = Widget 
    serializer_class = WidgetSerializer 
    filter_backends = (filters.DjangoFilterBackend,) 
    filter_fields = ('widget_type', 'widget_owner') 

    def get_queryset(self): 
     """ 
     Overwrite the query set to check permissions 
     """ 
     qs_list = [w.id for w in self.model.objects.all() if 
        canReadWidget(self.request.user, w)] 
     return self.model.objects.filter(id__in=qs_list) 

這工作,但我覺得像get_queryset功能可以改善。因爲我的canReadWidget是自定義的,所以我必須評估self.model.objects.all()並檢查用戶可以讀取哪些小部件,但該函數必須返回一個查詢集,以便使用id__in=qs_list部分。結果是,我做了兩次數據庫調用,實際上只是一次列表提取。

是否有一種標準的方法來處理這種按通用列表視圖進行的對象過濾?

+2

'canReadWidget'在做什麼?你能發佈代碼嗎? – ilse2005

+0

canReadWidget相當複雜 - 基本上,Widgets存在於樹中,其中一些小部件是另一個小部件類型的子項。用戶可以在樹中的任何級別擁有權限。所以基本上canReadWidget(user,WidgetA)會檢查用戶是否擁有WidgetA的權限,如果是的話它將返回True或False,否則它會查找WidgetA的父級以查看是否有權限繼承,等等直到找到一個或返回false。 –

+2

你可以看看django-guardian的對象權限。但看到你已經實現了你自己的分層權限邏輯,你可能不想切換到新的進程。只要您無法使用SQL連接來制定權限邏輯(通過創建您自己的QueryManager實現或使用自定義過濾器查詢),就無法像現在這樣避免評估和重新獲取。 – Risadinha

回答

1

在某些時候,最好放棄默認的通用視圖或功能並自行推出。

您應該看看ListModelMixin並覆蓋list來處理列表,而不是將其轉換爲查詢集。

您應該調整過濾和分頁,但是不會像當前那樣擊中數據庫兩次。