自动发现项目中所有有别名的URL,效果如下:

customer_list {'name': 'customer_list', 'url': '/customer/list/'}
customer_add {'name': 'customer_add', 'url': '/customer/add/'}
customer_edit {'name': 'customer_edit', 'url': '/customer/edit/(?P<cid>\\d+)/'}
customer_del {'name': 'customer_del', 'url': '/customer/del/(?P<cid>\\d+)/'}
customer_import {'name': 'customer_import', 'url': '/customer/import/'}
customer_tpl {'name': 'customer_tpl', 'url': '/customer/tpl/'}
payment_list {'name': 'payment_list', 'url': '/payment/list/'}
payment_add {'name': 'payment_add', 'url': '/payment/add/'}
payment_edit {'name': 'payment_edit', 'url': '/payment/edit/(?P<pid>\\d+)/'}
payment_del {'name': 'payment_del', 'url': '/payment/del/(?P<pid>\\d+)/'}
rbac:role_list {'name': 'rbac:role_list', 'url': '/rbac/role/list/'}
rbac:role_add {'name': 'rbac:role_add', 'url': '/rbac/role/add/'}
rbac:role_edit {'name': 'rbac:role_edit', 'url': '/rbac/role/edit/(?P<pk>\\d+)/'}
rbac:role_del {'name': 'rbac:role_del', 'url': '/rbac/role/del/(?P<pk>\\d+)/'}
rbac:user_list {'name': 'rbac:user_list', 'url': '/rbac/user/list/'}
rbac:user_add {'name': 'rbac:user_add', 'url': '/rbac/user/add/'}
rbac:user_edit {'name': 'rbac:user_edit', 'url': '/rbac/user/edit/(?P<pk>\\d+)/'}
rbac:user_del {'name': 'rbac:user_del', 'url': '/rbac/user/del/(?P<pk>\\d+)/'}
rbac:user_reset_pwd {'name': 'rbac:user_reset_pwd', 'url': '/rbac/user/reset/password/(?P<pk>\\d+)/'}
rbac:menu_list {'name': 'rbac:menu_list', 'url': '/rbac/menu/list/'}
rbac:menu_add {'name': 'rbac:menu_add', 'url': '/rbac/menu/add/'}
rbac:menu_edit {'name': 'rbac:menu_edit', 'url': '/rbac/menu/edit/(?P<pk>\\d+)'}
rbac:menu_del {'name': 'rbac:menu_del', 'url': '/rbac/menu/del/(?P<pk>\\d+)'}
rbac:second_menu_add {'name': 'rbac:second_menu_add', 'url': '/rbac/second/menu/add/(?P<menu_id>\\d+)/'}
rbac:second_menu_edit {'name': 'rbac:second_menu_edit', 'url': '/rbac/second/menu/edit/(?P<pk>\\d+)/'}
rbac:second_menu_del {'name': 'rbac:second_menu_del', 'url': '/rbac/second/menu/del/(?P<pk>\\d+)/'}
rbac:permission_add {'name': 'rbac:permission_add', 'url': '/rbac/permission/add/(?P<second_menu_id>\\d+)/'}
rbac:permission_edit {'name': 'rbac:permission_edit', 'url': '/rbac/permission/edit/(?P<pk>\\d+)/'}
rbac:permission_del {'name': 'rbac:permission_del', 'url': '/rbac/permission/del/(?P<pk>\\d+)/'}
rbac:multi_permissions {'name': 'rbac:multi_permissions', 'url': '/rbac/multi/permissions/'}

一、配置路由

rbac/urls.py

from django.urls import re_path

...
from rbac.views import menu
...
urlpatterns = [
...
# 批量操作权限
re_path(r'^multi/permissions/$', menu.multi_permissions, name='multi_permissions') # 自动发现项目中的所有URL
...
]

二、自动发现URL功能实现

排除不用发现的URL

settings.py

...
AUTO_DISCOVER_EXCLUDE = [
'/admin/',
'/login/',
]
...

rbac/service/router.py

import re
from collections import OrderedDict from django.conf import settings
from django.utils.module_loading import import_string # 根据字符串的形式,帮我们去导入模块
from django.urls import URLPattern, URLResolver # 路由分发:URLResolver。非路由分发:URLPattern def check_url_exclude(url):
"""
排除一些特定的url
:param url:
:return:
"""
for regex in settings.AUTO_DISCOVER_EXCLUDE:
if re.match(regex, url):
return True def recursion_urls(pre_namespace, pre_url, urlpatterns, url_ordered_dict):
"""
:param pre_namespace: namespace前缀(rbac:xxx),以后用于拼接name
:param per_url: url的前缀(rbac/xxx),以后用于拼接url
:param urlpatterns: 路由关系列表
:param url_ordered_dict: 用于保存递归中获取的所有路由
:return:
""" # 路由分发:URLResolver。非路由分发:URLPattern
for item in urlpatterns:
if isinstance(item, URLPattern): # 非路由分发,将路由添加到url_ordered_dict
if not item.name: # url中反向命名的name,没有的话不做处理,直接跳过。
continue
if pre_namespace: # 如果有命名空间就进行拼接。示例:rbac:role_list
name = f'{pre_namespace}:{item.name}'
else:
name = item.name # 示例:role_list # 判断url有没有前缀,如果有前缀的话我们要给它拼接上,一般url都是有前缀的,因为从根级路由开始我们就加了个/
# 下面两种写法都可以
url = pre_url + str(item.pattern)
# url = pre_url + item.pattern.regex.pattern # pattern.regex.pattern是拿到当前url django 1.X里是 url._regex
# 拼接完长这样:/^rbac/^user/edit/(?P<pk>\d_+)/$
url = url.replace('^', '').replace('$', '').replace('\/', '/')
# 把起始符和终止符替换成空的,最后得到:/rbac/user/edit/(?P<pk>\d_+)/
# django2.0中的path会多一个反斜杠\,例子:'/rbac\/permission/del/(?P<pk>\d+)/'
# 为了兼容django2.0中的path,要把\/换成/,最后成为:/rbac/permission/del/(?P<pk>\d+)/ if check_url_exclude(url): # 判断是否admin、login等我们不需要的url,是的话直接跳过
continue url_ordered_dict[name] = {'name': name, 'url': url}
# 'rbac:menu_list':{name:'rbac:menu_list',url:'xxxxx/yyyy/menu/list'} elif isinstance(item, URLResolver): # 路由分发,进行递归操作
if pre_namespace:
"""
# 有前缀 示例:admin,admin.site.urls的urls的返回值是:
@property
def urls(self):
return self.get_urls(), 'admin', self.name。 返回值的第二个是命名空间
"""
if item.namespace: # 如果有自己的namespace比如说user_list,和前面的pre_namespace进行拼接,结果是rbac:user_list:user_list里的url
namespace = f"{pre_namespace}:{item.namespace}"
else:
"""
自己没有namespace,但是父级有,那么namespace就是None
示例:re_path(r'^role/list/$', include('xxx.urls'))。rbac里的一条路由又进行路由分发,但是自己没有命名空间
"""
namespace = item.namespace
else:
if item.namespace: # 父级没有namespace,自己有。示例:re_path(r'^rbac/', include(('rbac.urls', 'rbac')), )
namespace = item.namespace
else: # 父级没有namespace,自己也没有
namespace = None # 下面两种写法都可以
recursion_urls(namespace, pre_url + str(item.pattern), item.url_patterns, url_ordered_dict)
# recursion_urls(namespace, pre_url + item.pattern.regex.pattern, item.url_patterns, url_ordered_dict) """
pre_url(上一级的url) + item.pattern.regex.pattern(当前路由分发的前缀),item.url_patterns(当前路由分发的urlpatterns)
拿re_path(r'^rbac/', include(('rbac.urls', 'rbac')))举例:
namespace = rbac, pre_url=/, item.pattern.regex.pattern=^rbac/,item.url_patterns = rbac.urls下的所有url
在django1.x里item.pattern.regex.pattern要换成item.regex.pattern
       如果rbac里还有路由分发的话,比如说rbac2,那么pre_url + str(item.pattern) 就是 rbac/rbac2,传到非路由分发的方法那就会继续拼接成如:rbac/rbac2/add/
""" def get_all_url_dict():
"""
获取项目中所有的URL(必须有name别名)
:return:
""" url_ordered_dict = OrderedDict() all_url = import_string(settings.ROOT_URLCONF) # from permission_learn import urls recursion_urls(None, '/', all_url.urlpatterns, url_ordered_dict) # 递归的去获取所有的路由。根目录没有namespace,根路由用/ # 得到类似这样的结果:
"""
{
'rbac:menu_list':{name:'rbac:menu_list',url:'xxxxx/yyyy/menu/list'}
}
""" return url_ordered_dict

三、在视图函数引用

rbac/views/menu.py

...
from rbac.service.router import get_all_url_dict
... ...
def multi_permissions(request):
"""
批量操作权限
:param request:
:return:
""" # 获取项目中所有的url all_url_dict = get_all_url_dict()
for k, v in all_url_dict.items():
print(k, v) return HttpResponse('ok it')
...

以后我们需要在页面展示这些URL,并对其进行增删改和权限操作

权限组件(12):自动发现项目中有别名的URL的更多相关文章

  1. 自动发现项目中的所有URL

    我的rbac组件,是想用到任何一个,项目中的. so 问题来了. - 问题: 拿到一个项目. 怎样获取到,当前项目中, 所有的URL 以及 每个URL的别名name, 还有是有 namespace 命 ...

  2. django2自动发现项目中的url

    根据路飞学城luffycity.com 的crm项目修改的 1 url入口:rbac/urls.py urlpatterns = [ ... # 批量操作权限 re_path(r'^multi/per ...

  3. 自动发现项目中的URL,django1版本和django2版本

    一.django 1 版本 routers.py import re from collections import OrderedDict from django.conf import setti ...

  4. rbac权限组件整合到实际项目的全过程详述

    rbac简介 项目的GitHub地址 欢迎Download&Fork&Star:https://github.com/Wanghongw/CombineRbac 另外,本文只简单介绍一 ...

  5. 自动发现项目中的url

    def check_url_exclude(url): """ 判断url是否需要自动被发现,如果不是则移除 :param url: 自动发现的url :return: ...

  6. zabbix自动发现功能实现批量web url监控

    需求: 现在有大量url需要监控,形式如http://www.baidu.com ,要求url状态不为200即报警. 需求详细分析: 大量的url,且url经常变化,现在监控用的是zabbix,如果手 ...

  7. Django自动获取项目中的全部URL

    import re from collections import OrderedDict from django.conf import settings from django.utils.mod ...

  8. CRM第一篇:权限组件之权限控制

    一.权限组件(1):一级菜单 二.权限组件(2):二级菜单 三.权限组件(3):默认选中非菜单(二级菜单) 四.权限组件(4):给动态菜单增加面包屑导航 五.权限组件(5):权限粒度控制到按钮 六.权 ...

  9. Django - 权限分配、权限组件与CRM整合

    一.权限分配 需求:为用户分配角色,为角色分配权限,如下图效果: 1.视图代码: from django.shortcuts import render from django.http import ...

随机推荐

  1. 爱上MVC~业务层刻意抛出异常,全局异常的捕获它并按格式返回

    回到目录 对于业务层的程序的致命错误,我们一直的做法就是直接抛出指定的异常,让程序去终断,这种做法是对的,因为如果一个业务出现了致命的阻塞的问题,就没有必要再向上一层一层的返回了,但这时有个问题,直接 ...

  2. 在MFC对话框中快速集成三维控件

    在MFC的对话框中可以方便的集成AnyCAD三维控件(c++版本),遵循一下几步: 1.在对话框资源中增加一个Static控件,ID为IDC_STATIC_3D,并且把它的Notify属性设置为Tru ...

  3. hibernate课程 初探单表映射3-5 hibernate增删改查

    本节简介: 1 增删改查写法 2 查询load和查询get方法的区别 3 demo 1 增删改查写法 增加 session.save() 修改 session.update() 删除 session. ...

  4. ps使用

    1.图片剪裁 1.按快捷键M(矩形选择工具)-> 选中要扣出的图片(按shift可正方形)->按快捷键C(剪裁工具)->双击鼠标选中区域,剪裁成功. 2.选中psd中的图标 1.按快 ...

  5. win10 asp+access

    今天是灰色的一天. 大清早来到单位,告知:单位主页访问不了! 我远程看了下.所有的文件后缀都变成了.crab 赶紧上网查下,哎呀我的妈呀,这是中了勒索病毒啊. 还用查?打开服务器,有个打开的文本文件写 ...

  6. SpringBoot JUnit4的断言和注解

    Junit4的断言常用方法: assertArrayEquals( new Object[]{ studentService.likeName("小明2").size() > ...

  7. UGUI的事件系统分析

    UGUI的源码还是非常清晰的,打开源码可以发现, 从UGUI的源码可知:在EventSystem中调用每一帧函数来实现: private void TickModules() { for (var i ...

  8. hbase查询语法

    1.scan '表名',{FILTER=>"PrefixFilter('rowkey值')"} scan 'useractions',{FILTER=>"Pr ...

  9. POJ1061 青蛙的约会 __一维世界的爱情

    由于今天上午在做数论知识的笔记,发现那时候赵老师讲的线性丢番图(求ax+by=c的特解)部分完全搞不懂,后来网上查了一下才发现这个公式就是求同余方程,所用方法就是扩展欧几里得算法.正好红皮书上有这么一 ...

  10. linux 命令——19 find (转)

    Linux 下find命令在目录结构中搜索文件,并执行指定的操作.Linux下find命令提供了相当多的查找条件,功能很强大.由于find具有强大的功能,所 以它的选项也很多,其中大部分选项都值得我们 ...