Without further ado, let’s get right to the code.

from django.urls import get_resolver, URLPattern, URLResolver


def get_all_url(resolver=None, pre='/') :
    if resolver is None:
        resolver = get_resolver()
    for r in resolver.url_patterns:
        if isinstance(r, URLPattern):
            if '<pk>' in str(r.pattern):
                continue
            yield pre + str(r.pattern).replace(A '^'.' ').replace('$'.' '), r.name
        if isinstance(r, URLResolver):
            yield from get_all_url(r, pre + str(r.pattern))
            
            
if __name__ == '__main__':
    Get the full url of the project
    for url, name in get_all_url():
        print("url='{}' name='{}'".format(url, name))
        
    Get all urls under an app
    # Imagine an app called Dashboard
    # pass the prefix with the pre argument
    for url, name in get_all_url(get_resolver('dashboard.urls')) :print("url='{}' name='{}'".format(url, name))
Copy the code

The get_resolver function is used. Let’s look at the source code and see how this function is used.

# django/urls/resolvers.py

def get_resolver(urlconf=None) :
    if urlconf is None:
        urlconf = settings.ROOT_URLCONF
    return _get_cached_resolver(urlconf)


@functools.lru_cache(maxsize=None)
def _get_cached_resolver(urlconf=None) :
    return URLResolver(RegexPattern(r'^/'), urlconf)
Copy the code

ROOT_URLCONF, which has a default settings.ROOT_URLCONF, is printed as myproject.urls, which is the global routing file for the project.

The return value is URLResolver class, this class is more complex, read the source code is not very clear how to deal with this class.

# django/urls/resolvers.py

class URLResolver:
    # Omitted a bunch of code

    @cached_property
    def urlconf_module(self) :
        if isinstance(self.urlconf_name, str) :return import_module(self.urlconf_name)
        else:
            return self.urlconf_name

    @cached_property
    def url_patterns(self) :
        # urlconf_module might be a valid set of patterns, so we default to it
        patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
        try:
            iter(patterns)
        except TypeError as e:
            msg = (
                "The included URLconf '{name}' does not appear to have any "
                "patterns in it. If you see valid patterns in the file then "
                "the issue is probably caused by a circular import."
            )
            raise ImproperlyConfigured(msg.format(name=self.urlconf_name)) from e
        return patterns
Copy the code

But there’s one method that stands out to me, because we’re going to fetch urls, and we’re going to have to pay special attention to urL-related functions.

Print this out and see if you can find anything.

print(get_resolver('myproject.urls').url_patterns)

# output
# [
#...
# <URLPattern 'api/v1/api-doc' [name='api-doc']>, 
# <URLResolver <URLPattern list> (api-docs:api-docs) # 'api/v1/drf-api-doc'>]
Copy the code

The result is a list of two types of elements, the URLPattern class and the URLResolver class.

# django/urls/resolvers.py

class URLPattern:
    def __init__(self, pattern, callback, default_args=None, name=None) :
        self.pattern = pattern
        self.callback = callback  # the view
        self.default_args = default_args or {}
        self.name = name
Copy the code

The former can get the corresponding URL directly, while the latter can also get the result recursively.

This is where we can declare ourselves done.


Follow the public account AlwaysBeta, a variety of back-end development technology dry goods.

Reference article:

  • www.ikaze.cn/article/60