使用Django REST Framework的ListCreateAPIView时,如何为POST和List等不同方法设置不同的权限

时间:2015-01-15 15:15:16

标签: django django-rest-framework

我构建了一个Follow模型来记录社交网络行为,并希望模拟以下操作。每个经过身份验证的用户都可以关注其

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功能?

2 个答案:

答案 0 :(得分: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)

我通过覆盖FollowingDelete函数使get_object()视图成功运行。

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")

答案 1 :(得分: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中获取用户(如果用户不存在则不允许)并检查他们是否是当前用户。