2016-03-04 81 views
2

我查看了CreateAPIView的代碼,並且在創建過程中無處檢查權限。所以我決定檢查他們在perform_create鉤如下:Django Rest框架中CreateAPIView的權限

class CourseList(generics.CreateAPIView): 
    """ 
    Create a course. 
    A user can create a course if he/she is an instructor in 
    the academy the course is to be created in. 
    """ 
    serializer_class = CourseRef 
    queryset = Course.objects.all() 
    permission_classes = (IsAuthenticated, IsInstructorInAcademy) 

    def perform_create(self, serializer): 
     self.check_object_permissions(self.request, serializer.validated_data.get('academy')) 
     serializer.save() 

該權限的樣子:

class IsInstructorInAcademy(BasePermission): 
    def has_object_permission(self, request, view, academy): 
     return request.user.instructor_set.filter(academy=academy).exists() 

當我嘗試創建過程中,最初的權限檢查運行正常和課程被保存,但隨即我得到以下錯誤:

ValueError at /api/courses/ 
Cannot query "Mathematics 11A": Must be "Academy" instance. 

,這提高在權限檢查,其結果是POST返回500 ISE的結果。

(這是稍微哈克,因爲我傳遞學院例如在權限檢查在perform_create掛鉤,而認爲真正擔心的課程。我考慮過使用許可IsInstructorInAcademyOfObject但對於這一點,我需要在傳遞對象,除非保存序列化程序,否則我無法獲得該對象。)

什麼是在此檢查權限的最佳方法?

回答

1

您遇到了問題,因爲您正在使用權限綁定業務邏輯檢查。

代替調用check_object_permission,請在執行反序列化後執行自己的檢查,如果檢查失敗,請提出PermissionDenied

+0

我想了解'業務邏輯檢查'和'權限'之間的區別,因爲即使在這裏,測試是在用戶。我正在檢查這是否是某種用戶,請允許這個/那個。 – slider

+0

當然,但是您的測試意味着您在請求內容已知之前執行權限檢查時知道請求的內容。 – Linovia

+0

我認爲請求的內容不是問題。問題在於學院實例(或者當你提到'請求內容?'時,你的意思是?)。但除此之外,請求內容何時已知?除此之外,執行此檢查的最佳位置是什麼? 'perform_create'裏面? – slider