2015-01-15 131 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")