如何将DRF视图集中重复的权限判断逻辑复用为permission_class?
DRF视图集重复权限逻辑的复用方案
你这段判断用户权限的逻辑不适合用permission_class来复用,因为DRF的permission_classes是用来做接口访问权限校验的(比如判断用户能不能调用这个接口),而你的场景是在用户已具备访问权限的前提下,根据权限分支执行不同业务逻辑。更合适的方式是把这段逻辑提取成视图集的复用方法,具体实现如下:
方案一:在当前视图集内封装复用方法
直接在MyViewSet里新增一个判断用户权限的方法,替代重复代码:
class MyViewSet(ModelViewSet): serializer_class = MySerializer queryset = models.MyClass.objects.all() def is_privileged_user(self): """判断当前用户是否拥有owner或admin权限""" permission = self.request.user.permission return permission in ('owner', 'admin') def get_serializer_class(self): if self.is_privileged_user(): return self.serializer_class else: return OtherSerializer def perform_create(self, serializer): if self.is_privileged_user(): serializer.save() else: employee = models.Employee.objects.get(user=self.request.user) serializer.save(employee=employee)
这样既消除了代码重复,还通过方法名明确了逻辑含义,提升了代码可读性。
方案二:基类视图集跨视图复用
如果这段权限判断逻辑需要在多个视图集里使用,可以把它放到一个基类视图集中,其他视图集继承这个基类即可:
# 定义基类视图集,封装通用权限判断逻辑 class PrivilegedBaseViewSet(ModelViewSet): def is_privileged_user(self): permission = self.request.user.permission return permission in ('owner', 'admin') # 业务视图集继承基类,直接使用复用方法 class MyViewSet(PrivilegedBaseViewSet): serializer_class = MySerializer queryset = models.MyClass.objects.all() def get_serializer_class(self): if self.is_privileged_user(): return self.serializer_class else: return OtherSerializer def perform_create(self, serializer): if self.is_privileged_user(): serializer.save() else: employee = models.Employee.objects.get(user=self.request.user) serializer.save(employee=employee)
为什么不用permission_class?
DRF的permission_classes核心作用是拦截无权限用户的接口请求,验证不通过时会直接返回403状态码。而你的场景是用户已经能正常访问接口,只是需要根据权限执行不同的业务逻辑,和权限校验的定位不符,所以用自定义方法是更合理的选择。
内容的提问来源于stack exchange,提问作者Waleed Farrukh
相关产品推荐
相关产品推荐

