2015-02-09 65 views
0

我有3個對象 - 企業,專家和RecentProject其中RecentProject有ForeignKey的對公司和多對多關係專家:保存在Django的REST框架嵌套的單個對象

class RecentProject(BaseProfileObject): 
    company = models.ForeignKey(
     'experts.Company', 
     verbose_name=_("Company"), 
     blank=True, 
     null=True, 
     related_name='projects') 
    experts = models.ManyToManyField(
     "Expert", 
     verbose_name=_("Experts"), 
     blank=True, 
     null=True, 
     related_name='projects') 
    class Meta: 
     verbose_name = _("Recent project") 
     verbose_name_plural = _("Recent projects") 

什麼,我要的是能夠發佈新從終點最近的一個項目像

API/V1 /公司/ 1/recentprojects /和API/V1 /專家/ 1/recentprojects/

在第一種情況下的seralizer應該能夠驗證(或者說做權限檢查)如果用戶可以更改公司和在第二種情況下,如果用戶可以對專家進行更改。 我似乎無法找到的是一個如何使權限知道父對象(第一個案例中的公司和第二個案例中的專家)的示例。

據我所知,它可以與權限來完成,所以我創建的權限,如:

class UserCanModifyCompany(permissions.BasePermission): 
    def has_permission(self, request, view): 
     # Do check here 
     return False 

而且我把它添加到我的視圖集: 類RecentProjectViewSet(viewsets.ModelViewSet): 查詢集= RecentProject.objects。所有() serializer_class = RecentProjectSerializer

@permission_classes((UserIsAuthenticatedExpert, UserCanModifyCompany)) 
def create(self, request, *args, **kwargs): 
    return super(RecentProjectViewSet, self).create(request, *args, **kwargs) 

@permission_classes((UserIsAuthenticatedExpert, UserCanModifyCompany)) 
def update(self, request, *args, **kwargs): 
    return super(RecentProjectViewSet, self).update(request, *args, **kwargs) 

但我怎樣才能確保權限檢查具有可用於公司/專家訪問檢查信息。或者,我是否需要爲公司/專家最近的項目保存創建不同的視圖集,併爲它們設置不同的權限類?

回答

2

首先,爲同一資源創建兩個不同的端點不是一個好主意。我建議你使用單個端點:api/v1/recentprojects/。 話雖如此,我一直處於類似的情況,我認爲你最好的選擇是使用@detail_route公司和專家的觀點集。 例如,在你的ExpertViewSet

@detail_route(methods=['post'], , permission_classes=[UserIsAuthenticatedExpert, UserCanModifyCompany]) 
    def recentprojects(self, request, pk=None): 
     expert = self.get_object() 
     serializer = RecentProjectSerializer(data=request.data) 
     if serializer.is_valid(): 
      recent_project = serializer.save(company=somecompany) 
      recent_project.experts.add(expert) 
      return Response({'status': 'ok'}) 
     else: 
      return Response(serializer.errors, 
          status=status.HTTP_400_BAD_REQUEST) 

這將讓你近期發佈新項目api/v1/experts/{pk}/recentprojects/。 至於權限,則需要實現has_object_permission,因爲這是一個單獨的對象端點:

class UserIsAuthenticatedExpert(permissions.BasePermission): 

    def has_object_permission(self, request, view, obj): 
     return some_condition 

您還可以self.action覆蓋get_queryset一起過濾專家或公司實例端點可以操作,但是這將提高404錯誤,而不是403.

+0

感謝您的回答。我實際上嘗試使用UserCanModifyCompany與has_object_permission方法,但該方法從來沒有被調用,所有通過api發佈的項目都被保存,沒有得到403. – 2015-02-09 10:27:30

+0

此外,什麼決定了詳細路線的網址?您的detail_route裝飾器具有請求方法和權限類。網址來自哪裏 - 當我使用ExpertViewSet的詳細路線,那麼什麼網址照顧這篇文章? – 2015-02-09 10:29:01

+0

@OdifYltsaeb默認情況下,函數名稱將用作資源URL之後的url部分,即'^ experts/pk/function_name'。這是由路由器決定的。要覆蓋它,請將'url_path ='recent-projects''傳遞給'detail_route'裝飾器。有關詳細信息,請參閱路由器文檔:http://www.django-rest-framework.org/api-guide/routers/#extra-link-and-actions – almalki 2015-02-09 11:00:55

相關問題