2015-01-15 134 views
1

不同的方法,如POST和列表設置不同的權限我建立了一個Follow模型來記錄社交網絡的行爲,並希望模擬以下操作。每個經過認證的用戶都可以跟隨其他人。如何使用Django REST框架的ListCreateAPIView

class Follow(models.Model): 
    user = models.ForeignKey(User) 
    follower = models.ForeignKey(User, related_name="followers") 
    follow_time = models.DateTimeField(auto_now_add=True, blank=True) 

    class Meta: 
     unique_together = ('user', 'follower') 

    def __unicode__(self): 
     return u'%s, %s' % (self.user.username, self.follower) 

而且FollowSerializer是:

class FollowSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Follow 
     field = ('user', 'follower', 'follow_time') 

,我使用的觀點是:

class FollowingEnumByUserID(generics.ListCreateAPIView): 
    serializer_class = FollowSerializer 

    def get_queryset(self): 
     follower_id = self.kwargs['pk'] 
     return Follow.objects.filter(follower=follower_id) 

我對其進行註冊的網址爲:

url(r'^api/users/(?P<pk>[0-9]+)/following/$', views.FollowingEnumByUserID.as_view()), 

每個已認證的用戶都可以查看下面的關係,沒有限制。但我想只允許經過身份驗證的用戶自行添加以下關係,這意味着應該有request.user == follower。我怎樣才能做到這一點?


我想補充的FollowingDelete視圖只允許用戶通過他/添加下面的關係自己。

所以我更新了url.py爲:

url(r'^api/users/(?P<pk>[0-9]+)/following/$', views.FollowingEnumByUserID.as_view()), 
url(r'^api/users/(?P<pk>[0-9]+)/following/(?P<following_id>[0-9]+)/$', views.FollowingDelete.as_view()), 

的許可,我現在用的就是:

class IsFollowerOrReadOnly(permissions.BasePermission): 
    """ 
    View-level permission to allow the follower to edit the following relation 
    """ 

    def has_permission(self, request, view): 
     if request.method in permissions.SAFE_METHODS: 
      return True 

     try: 
      follower = User.objects.get(id=view.kwargs["pk"]) 
     except User.DoesNotExist: 
      #Reject any request for an invalid user 
      return False 

     return follower == request.user 

和意見是:

class FollowingEnumByUserID(generics.ListCreateAPIView): 
    serializer_class = FollowSerializer 
    permission_class = (IsFollowerOrReadOnly) 

    def get_queryset(self): 
     """ 
     List all the people the input user is following 
     """ 
     follower_id = self.kwargs['pk'] 
     return Follow.objects.filter(follower=follower_id) 

class FollowingDelete(generics.DestroyAPIView): 
    serializer_class = FollowSerializer 
    permission_class = (IsAuthenticated, IsFollowerOrReadOnly) 

    def get_queryset(self): 
     user_id = self.kwargs['following_id'] 
     follower_id = self.kwargs['pk'] 
     return Follow.objects.filter(user=user_id, follower=follower_id) 

現在的問題是:

  1. 權限類不起作用。

  2. 如何重寫DestroyAPIView,我應該重寫get_queryset函數嗎?

回答

0

Django REST框架provides custom permission handling允許您處理視圖和對象級別的複雜權限。爲了做你正在尋找的東西,你將不得不去create a custom permission,但這很容易。

每個經過身份驗證的用戶都可以關注其他用戶。

DRF提供了一個IsAuthenticated權限,允許您非常輕鬆地完成此操作。你所要做的就是add it to the permission_classes on the view, or globally through the settings

from rest_framework import permissions 

class FollowingEnumByUserID(generics.ListCreateAPIView): 
    serializer_class = FollowSerializer 
    permission_classes = (permissions.IsAuthenticated,) 

    def get_queryset(self): 
     follower_id = self.kwargs['pk'] 
     return Follow.objects.filter(follower=follower_id) 

還有一個限制,就是需要自定義權限類的限制。

但我想只允許經過身份驗證的用戶自己添加以下關係/她

這就需要檢查請求的方法(我假設是POST)以及用戶誰被跟蹤。

讓我們以簡單的檢查,請求方法開始。 Django REST框架提供了檢查請求方法的權限類,such as IsAuthenticatedOrReadOnly,因此we can look at the code查看它是如何完成的。從那裏只需要檢查請求類型。

class PostIfFollower(BasePermission): 
    """ 
    The request is not POST or the request user is the follower. 
    """ 

    def has_permission(self, request, view): 
     if request.method != "POST": 
      return True 

     return False 

此代碼將拒絕進來使用POST方法,同時讓所有其他的所有請求。創建此權限的第二步是執行用戶檢查,因此只有追隨者可以添加他們正在追蹤的新人。這需要獲得追隨者,並檢查request.user

class PostIfFollower(BasePermission): 
     """ 
     The request is not POST or the request user is the follower. 
     """ 

     def has_permission(self, request, view): 
      if request.method != "POST": 
       return True 

      try: 
       follower = User.objects.get(id=view.kwargs["pk"]) 
      except User.DoesNotExist: 
       # Reject any requests for an invalid user 
       return False 

      return follower == request.user 

這從URL(不允許它,如果用戶不存在)獲取用戶時,如果它們是當前用戶檢查是建立在過去的權限類。

+0

嗨,@凱文,請問您是否可以回答上述問題? – Scofield77 2015-01-18 03:16:04

+0

@ Scofield77乍看之下,您的修改後的代碼似乎應該適用於您正在嘗試執行的操作。我會推薦[創建一個新問題](https://stackoverflow.com/questions/ask),而不是修改這個問題,因爲它似乎是一個不同的問題。另外,歡迎來到Stack Overflow! – 2015-01-18 03:31:33

1

我修改錯別字後,允許類的工作現在:

class FollowingEnumByUserID(generics.ListCreateAPIView): 
    serializer_class = FollowSerializer 
    permission_classes = (IsFollowerOrReadOnly,) 

    def get_queryset(self): 
     """ 
     List all the people the input user is following 
     """ 
     follower_id = self.kwargs['pk'] 
     return Follow.objects.filter(follower=follower_id) 

class FollowingDelete(generics.DestroyAPIView): 
    serializer_class = FollowSerializer 
    permission_classes = (IsAuthenticated, IsFollowerOrReadOnly,) 

    def get_queryset(self): 
     user_id = self.kwargs['following_id'] 
     follower_id = self.kwargs['pk'] 
     return Follow.objects.filter(user=user_id, follower=follower_id) 

而且我通過重寫get_object()功能使FollowingDelete視圖工作順利。

def get_object(self, *args, **kwargs): 
    user_id = self.kwargs['following_id'] 
    follower_id = self.kwargs['pk'] 

    try: 
     return Follow.objects.get(user=user_id, follower=follower_id) 
    except Follow.DoesNotExist: 
     raise Http404("No such following relation")