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

Posted lshedward

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自动发现项目中的URL,django1版本和django2版本相关的知识,希望对你有一定的参考价值。

一、django 1 版本

routers.py

import re
from collections import OrderedDict

from django.conf import settings
from django.utils.module_loading import import_string  # 根据字符串的形式,帮我们去导入模块
from django.urls import RegexURLResolver, RegexURLPattern # 路由分发:URLResolver。不是路由分发:URLPattern


def check_url_exclude(url):
    """
    排除一些特定的url
    :param url:
    :return:
    """
    exclude_url = [
        /admin.*,
        /login/
    ]
    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:......),以后用于拼接name
    :param pre_url: url的前缀(rbac/......),以后用于拼接url
    :param urlpatterns: 路由关系列表
    :param url_ordered_dict: 用于保存递归中获取的所有路由
    :return:
    """
    for item in urlpatterns:
        if isinstance(item,RegexURLPatter):  # 非路由分发,将路由添加到url_ordered_dict
            if not item.name:  # url中反向命名的name
                continue
            if pre_namespace:
                name = f"{pre_namespace}:{item.name}"
            else:
                name = item.name
            url = pre_url + item.item._regex  # /^rbac/^user/edit/(?P<pk>d_+)/$
            url = url.replace(^, ‘‘).replace($, ‘‘)  # /rbac/user/edit/(?P<pk>d_+)/

            if check_url_exclude(url):
                continue
            url_ordered_dict[name] = {name: name, url: url}

        elif isinstance(item,  RegexURLResolver):  # 路由分发,进行递归操作
            if pre_namespace:
                if item.namespace:
                    namespace = f"{pre_namespace}:{item.namespace}"
                else:
                    namespace = item.namespace
            else:
                if item.namespace:
                    namespace = item.namespace
                else:
                    namespace = None
            recursion_urls(namespace, pre_url + item.regex.pattern, item.url_patterns, url_ordered_dict)


def get_all_url_dict():
    """
    获取项目中所有的URL(必须有name别名)
    :return:
    """
    url_ordered_dict = OrderedDict()
    """
    {
        ‘rbac:menu_list‘:{name:‘rbac:menu_list‘,url:‘xxxxx/yyyy/menu/list‘}
    }
    """

    md = import_string(settings.ROOT_URLCONF)  # from permision_learn import urls

    recursion_urls(None, /, md.urlpatterns, url_ordered_dict)  # 递归的去获取所有的路由。根目录没有namespace,根路由用/

    return url_ordered_dict

 

views.py

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(....)

 

二、django 2版本

django 2版本有些坑,和django 1版本的用法略有不同。谷歌查了半天,只查到模块名变了,没查到用法。没办法,只能取看源码,只能看到参数名变了,瞎试了试,居然能用。

routers.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:
    """
    exclude_url = [
        /admin.*,
        /login/
    ]
    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:......),以后用于拼接name
    :param pre_url: url的前缀(rbac/......),以后用于拼接url
    :param urlpatterns: 路由关系列表
    :param url_ordered_dict: 用于保存递归中获取的所有路由
    :return:
    """
    for item in urlpatterns:
        if isinstance(item, URLPattern):  # 非路由分发,将路由添加到url_ordered_dict
            if not item.name:  # url中反向命名的name
                continue
            if pre_namespace:
                name = f"{pre_namespace}:{item.name}"
            else:
                name = item.name
            url = pre_url + item.pattern.regex.pattern  # /^rbac/^user/edit/(?P<pk>d_+)/$
            url = url.replace(^, ‘‘).replace($, ‘‘)  # /rbac/user/edit/(?P<pk>d_+)/

            if check_url_exclude(url):
                continue
            url_ordered_dict[name] = {name: name, url: url}

        elif isinstance(item, URLResolver):  # 路由分发,进行递归操作
            if pre_namespace:
                if item.namespace:
                    namespace = f"{pre_namespace}:{item.namespace}"
                else:
                    namespace = item.namespace
            else:
                if item.namespace:
                    namespace = item.namespace
                else:
                    namespace = None
            recursion_urls(namespace, pre_url + item.pattern.regex.pattern, item.url_patterns, url_ordered_dict)


def get_all_url_dict():
    """
    获取项目中所有的URL(必须有name别名)
    :return:
    """
    url_ordered_dict = OrderedDict()
    """
    {
        ‘rbac:menu_list‘:{name:‘rbac:menu_list‘,url:‘xxxxx/yyyy/menu/list‘}
    }
    """

    md = import_string(settings.ROOT_URLCONF)  # from permision_learn import urls

    recursion_urls(None, /, md.urlpatterns, url_ordered_dict)  # 递归的去获取所有的路由。根目录没有namespace,根路由用/

    return url_ordered_dict

 

views.py

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(....)

以上是关于自动发现项目中的URL,django1版本和django2版本的主要内容,如果未能解决你的问题,请参考以下文章

Django2.0版本 path与Django1.x版本url正则匹配问题

django 如何知道创建项目/应用程序的版本

Django1.11加载静态文件

Python学习第120天(Django1和2之间的区别)

Django 1.6:清除一张表中的数据

Celery 4 不自动发现任务