从零开始搭建当然是可以的,但是Django的特色就是大而全,所以,我的方案是,利用现有的Django框架,实现功能。
我用的pycharm,操作很方便快捷。
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| django_content_type |
先看看你的数据库,这些表,就是咱们创建权限系统会使用的所有数据表了,都是自动生成的,少哪个,自己百度去。
想了解模型类,需要看源码。
源码如何查看方便?找到你的代码,随便找个地方,引用一下:
from django.contrib.auth.models import Permission
ctrl+鼠标左键,点击Permission,然后在打开的源码页面,上边的页面标签(auth/models.py)那里,右键,copy path,使用pycharm,点file,open,粘贴,删除粘贴字符串里面最后的“/models.py”,
... .../site-packages/django/contrib/auth
OK,open in new windows,OK,进去之后,像进入一个项目一样,这样非常有利于你了解源码。
如何快速了解一个Django项目?进去先看models。
如何一目了然的查看一个.py文件的结构?点pycharm的view,tool windows,structure,把一级标题都折叠起来!
现在,c 图标开头的,都是类,f 图标开头的都是函数。
update_last_login
PermissionManager
Permission
GroupManager
Group
UserManager
_user_get_all_permissions
_user_has_perm
_user_has_module_perms
PermissionsMixin
AbstractUser
User
AnonymousUser
百度翻译一下,了解这些类都是什么。不要全扔百度翻译,要先分词:
显然差别很大。
manager结尾的(PermissionManager),是模型管理器类,和他前面一样的(Permission),是模型类。其他也是。
Permission
Group
User
这三个类,就是咱们需要仔细了解的,干货!
看看他的字段,还有他的父类的字段。
Permission:
content_type = models.ForeignKey(
ContentType,
models.CASCADE,
verbose_name=_('content type'),
)
所以,你想创建权限,需要有对应的ContentType。
再去看看ContentType类,方法同上,ctrl+左键追踪源代码,复制路径,pycharm打开,了解一下。
class ContentType(models.Model):
app_label = models.CharField(max_length=100)
model = models.CharField(_('python model class name'), max_length=100)
就是字面意思,app名字和model名字。但是他的数据是根据你迁移时候,自动生成的,不是关联的。这意味着,咱们也可以,手动添加。
随便找个你项目里面的app,在admin.py里面加上
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
@admin.register(Permission)
class CompanyAdmin(admin.ModelAdmin):
list_display = ('id','name','content_type','codename')
@admin.register(ContentType)
class CompanyAdmin(admin.ModelAdmin):
list_display = ('id','app_label','model')
然后,打开django自带的后台,/admin,就可以看到这两个模型类:
如果groups和users没有,自己百度去,差不多的,应该。
from rest_framework.views import APIView
APIView里面的
def initial(self, request, *args, **kwargs):
"""
Runs anything that needs to occur prior to calling the method handler.
"""
self.format_kwarg = self.get_format_suffix(**kwargs)
# Perform content negotiation and store the accepted info on the request
neg = self.perform_content_negotiation(request)
request.accepted_renderer, request.accepted_media_type = neg
# Determine the API version, if versioning is in use.
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme
# Ensure that the incoming request is permitted
self.perform_authentication(request)
self.check_permissions(request)
self.check_throttles(request)
这个的意思是,initial初始化的时候,会走这几步。咱们创建一个APIView的子类,把check_permissions重写一下,然后,需要检查接口权限的视图类,直接继承这个新写的CheckPermissionView,就可以完成,每个接口都检测是否拥有权限的需求。
class CheckPermissionView(AllowAnyView):
def check_permissions(self, request):
# print(request.path_info)
# print(self.__class__.__name__)
codename = request.path_info.split("/")[1] + "/" + self.__class__.__name__
# print(codename) # app_name/view_class_name
if codename[0] == "/":
codename = "swagger"
user_id = request.user.id
# print('user_id '*30)
# print(user_id)
if not user_id:
raise BusinessException("请登录之后再访问此接口")
group = Group.objects.filter(permissions__codename=codename,user__id=user_id).first()
if not group:
raise BusinessException("你的权限不足以访问此接口,若有需要,请联系管理员开通权限")
BusinessException是一个自定义错误,继承自Exception,这里不多说,不会写的,百度一下。
至于权限名字是如何定义的,你把我的注释打开,打印出来,就知道了。
一个接口对应一个权限,可以把一堆接口权限,都分给一个新创建的groups,然后,需要这些权限的users,直接加入groups,就可以轻松实现,接口粒度的权限管理。
全程代码不多,但是需要对源码有一定程度的理解,其他就是填权限麻烦一点点(当然可以使用SQL直接插入数据库,我感觉这样快一点点。SQL直接代码操作,生成还是很快的。不用挨个填admin后台)。
如果我的文章,对你有一点点帮助的话,请帮忙在右边小心心那里点赞一下,码字不易,也是为了将来找工作好找一点,O(∩_∩)O谢谢!