自动发现项目中所有有别名的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 refrom collections import OrderedDictfrom django.conf import settingsfrom django.utils.module_loading import import_string ?# 根据字符串的形式,帮我们去导入模块from django.urls import URLPattern, URLResolver ?# 路由分发:URLResolver。非路由分发:URLPatterndef check_url_exclude(url): ???""" ???排除一些特定的url ???:param url: ???:return: ???""" ???for regex in settings.AUTO_DISCOVER_EXCLUDE: ???????if re.match(regex, url): ???????????return Truedef 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 + item.pattern.regex.pattern ?# pattern.regex.pattern是拿到当前url django 1.X里是 url._regex ???????????# 拼接完长这样:/^rbac/^user/edit/(?P<pk>\d_+)/$ ???????????url = url.replace(‘^‘, ‘‘).replace(‘$‘, ‘‘) ?# 把起始符和终止符替换成空的,最后得到:/rbac/user/edit/(?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 ???????????????????namespace = f"{pre_namespace}:{item.namespace}" ???????????????else: ???????????????????""" ???????????????????自己没有namespace,但是父级有,那么namespace就应该是父级的,所以那就直接应该是rbac。 ???????????????????示例:re_path(r‘^role/list/$‘, include(‘xxx.urls‘))。rbac里的一条路由又进行路由分发,但是自己没有命名空间 ???????????????????""" ???????????????????namespace = item.namespace ?# 写成namespace = pre_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 + 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 ???????????"""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
原文地址:https://www.cnblogs.com/lshedward/p/10518270.html