我构建了一个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)
现在的问题是:
许可类别完全不起作用。
如何重写DestroyAPIView
,是否应该覆盖get_queryset
功能?
答案 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中获取用户(如果用户不存在则不允许)并检查他们是否是当前用户。