本文共 4043 字,大约阅读时间需要 13 分钟。
目前已经完成了用户注册,登录验证和商品收藏的功能。但是还不够。还要有用户权限验证
比如 此收藏是否为用户自己的收藏。登录的用户是否有权限更改其他用户的收藏等
涉及到的库:
这两货不一样。 Auth是用于用户登录验证,Perm使用于用户权限验证
Permissions下这些验证库
AllowAny:不管有没有权限都可以访问。
IsAuthenticated: 判断是否已经登录
IsAdminUser:判断用户是否是一个管理员。根据此字段 user.is_staff
判断是否登录:(未登录访问时抛401错误给前端)
from utils.permissions import IsOwnerOrReadOnlyclass UserFavViewset(mixins.CreateModelMixin, mixins.ListModelMixin, mixins.DestroyModelMixin, viewsets.GenericViewSet): """ 用户收藏功能 """ permission_classes = (IsAuthenticated,)
自定义权限验证Custom permissions
IP白名单检测:
from rest_framework import permissionsclass BlacklistPermission(permissions.BasePermission): """ Global permission check for blacklisted IPs. """ def has_permission(self, request, view): ip_addr = request.META['REMOTE_ADDR'] blacklisted = Blacklist.objects.filter(ip_addr=ip_addr).exists() return not blacklisted
是否是用户本人,否则只读的例子:
class IsOwnerOrReadOnly(permissions.BasePermission): """ Object-level permission to only allow owners of an object to edit it. Assumes the model instance has an `owner` attribute. """ def has_object_permission(self, request, view, obj): # Read permissions are allowed to any request, # so we'll always allow GET, HEAD or OPTIONS requests. if request.method in permissions.SAFE_METHODS: return True # Instance must have an attribute named `owner`. return obj.owner == request.user
拿到教程项目中使用的例子
# 新建 utils/permissions.pyfrom rest_framework import permissionsclass IsOwnerOrReadOnly(permissions.BasePermission): """ Object-level permission to only allow owners of an object to edit it. Assumes the model instance has an `owner` attribute. """# 重写BasePermission中的has_object_permission函数# 用来判定所要操作对象的user字段是否等于request.user字段 def has_object_permission(self, request, view, obj): if request.method in permissions.SAFE_METHODS: return True return obj.user == request.user
使用该自定义Permission
# users_operation/views.pyclass UserFavViewset(mixins.CreateModelMixin, mixins.ListModelMixin, mixins.DestroyModelMixin, viewsets.GenericViewSet): """ 用户收藏功能 """# ---------------------------------------->这里 permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)
这样做完之后 如果要删除或修改的时候 会要求验证权限的。
不过这里也有问题,不能让某一用户获取到所有的收藏信息,其实也没必要全部获取到,获取到自己的不就完事了 。
所以需要重写get_queryset函数
def get_queryset(self): return UserFav.objects.filter(user=self.request.user)
类中配置queryset变量的参数可以删掉了
然后有一个小bug
要将这里改成self.user.username 否则xadmin获取某一用户收藏时会报错
class UserFav(models.Model): """ 用户收藏 """ user = models.ForeignKey(User, verbose_name=u'用户', on_delete=models.CASCADE) goods = models.ForeignKey(Goods, verbose_name=u'商品', on_delete=models.CASCADE) add_time = models.DateTimeField(default=datetime.now, verbose_name=u'添加时间') class Meta: verbose_name = u'用户收藏' verbose_name_plural = verbose_name unique_together = ("user", "goods") def __str__(self):# 这里 return self.user.username
之前我们将JWT验证放在了全局的settings.py中。这会有问题
不是每一个页面都需要验证。
所以我们需要将全局的JWT验证放到部分需要用户验证的view中
注释掉
在用户收藏中做示例
from rest_framework_jwt.authentication import JSONWebTokenAuthenticationfrom rest_framework.authentication import SessionAuthenticationclass UserFavViewset(mixins.CreateModelMixin, mixins.ListModelMixin, mixins.DestroyModelMixin, viewsets.GenericViewSet): """ 用户收藏功能 """# ------------------------------------------------------> 这个是用于DEF控制台的测试登录用 authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)
默认情况下
前端用户是通过表ID来读取相应字段。但是ID字段是数据库自动递增生成的。 但是鬼知道这些ID是对应哪个数据
所以 收藏的话 正常是希望通过商品id就能够访问到
所以需要这么干:
class UserFavViewset(mixins.CreateModelMixin, mixins.ListModelMixin, mixins.DestroyModelMixin, viewsets.GenericViewSet): """ 用户收藏功能 """ permission_classes = (IsAuthenticated, IsOwnerOrReadOnly) serializer_class = UserFavSerializer# 这里 lookup_field = "goods_id" authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)
这节 主要说的是 用户的权限验证,自定义queryset对象,局部JWT验证和generic views字段关联
完结
转载地址:http://miepi.baihongyu.com/