Skip to content

nautobot.apps.utils

Nautobot utility functions.

nautobot.apps.utils.get_url_for_url_pattern(url_pattern)

Given a URL pattern, construct a URL string that would match that pattern.

Examples:

>>> get_url_for_url_pattern("/plugins/example-plugin/^models/(?P<pk>[^/.]+)/$")
'/plugins/example-plugin/models/00000000-0000-0000-0000-000000000000/'
>>> get_url_for_url_pattern("/circuits/circuit-terminations/<uuid:termination_a_id>/connect/<str:termination_b_type>/")
'/circuits/circuit-terminations/00000000-0000-0000-0000-000000000000/connect/string/'
Source code in nautobot/utilities/utils.py
def get_url_for_url_pattern(url_pattern):
    """
    Given a URL pattern, construct a URL string that would match that pattern.

    Examples:
        >>> get_url_for_url_pattern("/plugins/example-plugin/^models/(?P<pk>[^/.]+)/$")
        '/plugins/example-plugin/models/00000000-0000-0000-0000-000000000000/'
        >>> get_url_for_url_pattern("/circuits/circuit-terminations/<uuid:termination_a_id>/connect/<str:termination_b_type>/")
        '/circuits/circuit-terminations/00000000-0000-0000-0000-000000000000/connect/string/'
    """
    url = url_pattern
    # Fixup tokens in path-style "classic" view URLs:
    # "/admin/users/user/<id>/password/"
    url = re.sub(r"<id>", "00000000-0000-0000-0000-000000000000", url)
    # "/silk/request/<uuid:request_id>/profile/<int:profile_id>/"
    url = re.sub(r"<int:\w+>", "1", url)
    # "/admin/admin/logentry/<path:object_id>/"
    url = re.sub(r"<path:\w+>", "1", url)
    # "/dcim/sites/<slug:slug>/"
    url = re.sub(r"<slug:\w+>", "slug", url)
    # "/apps/installed-apps/<str:app>/"
    url = re.sub(r"<str:\w+>", "string", url)
    # "/dcim/locations/<uuid:pk>/"
    url = re.sub(r"<uuid:\w+>", "00000000-0000-0000-0000-000000000000", url)
    # tokens in regexp-style router urls, including REST and NautobotUIViewSet:
    # "/extras/^external-integrations/(?P<pk>[^/.]+)/$"
    # "/api/virtualization/^interfaces/(?P<pk>[^/.]+)/$"
    # "/api/virtualization/^interfaces/(?P<pk>[^/.]+)\\.(?P<format>[a-z0-9]+)/?$"
    url = re.sub(r"[$^]", "", url)
    url = re.sub(r"/\?", "/", url)
    url = re.sub(r"\(\?P<app_label>[^)]+\)", "users", url)
    url = re.sub(r"\(\?P<class_path>[^)]+\)", "foo/bar/baz", url)
    url = re.sub(r"\(\?P<format>[^)]+\)", "json", url)
    url = re.sub(r"\(\?P<name>[^)]+\)", "string", url)
    url = re.sub(r"\(\?P<pk>[^)]+\)", "00000000-0000-0000-0000-000000000000", url)
    url = re.sub(r"\(\?P<slug>[^)]+\)", "string", url)
    url = re.sub(r"\(\?P<url>[^)]+\)", "any", url)
    # Fallthru for generic URL parameters
    url = re.sub(r"\(\?P<\w+>[^)]+\)\??", "unknown", url)
    url = re.sub(r"\\", "", url)

    if any(char in url for char in "<>[]()?+^$"):
        raise RuntimeError(f"Unhandled token in URL {url} derived from {url_pattern}")

    return url

nautobot.apps.utils.get_url_patterns(urlconf=None, patterns_list=None, base_path='/')

Recursively yield a list of registered URL patterns.

Parameters:

Name Type Description Default
urlconf URLConf

Python module such as nautobot.core.urls. Default if unspecified is the value of settings.ROOT_URLCONF, i.e. the nautobot.core.urls module.

None
patterns_list list

Used in recursion. Generally can be omitted on initial call. Default if unspecified is the url_patterns attribute of the given urlconf module.

None
base_path str

String to prepend to all URL patterns yielded. Default if unspecified is the string "/".

'/'

Yields:

Type Description
str

Each URL pattern defined in the given urlconf and its descendants

Examples:

>>> generator = get_url_patterns()
>>> next(generator)
'/'
>>> next(generator)
'/search/'
>>> next(generator)
'/login/'
>>> next(generator)
'/logout/'
>>> next(generator)
'/circuits/circuits/<uuid:pk>/terminations/swap/'
>>> import example_plugin.urls as example_urls
>>> for url_pattern in get_url_patterns(example_urls, base_path="/plugins/example-plugin/"):
...     print(url_pattern)
...
/plugins/example-plugin/
/plugins/example-plugin/config/
/plugins/example-plugin/models/<uuid:pk>/dynamic-groups/
/plugins/example-plugin/other-models/<uuid:pk>/dynamic-groups/
/plugins/example-plugin/docs/
/plugins/example-plugin/circuits/<uuid:pk>/example-plugin-tab/
/plugins/example-plugin/devices/<uuid:pk>/example-plugin-tab-1/
/plugins/example-plugin/devices/<uuid:pk>/example-plugin-tab-2/
/plugins/example-plugin/override-target/
/plugins/example-plugin/^models/$
/plugins/example-plugin/^models/add/$
/plugins/example-plugin/^models/import/$
/plugins/example-plugin/^models/edit/$
/plugins/example-plugin/^models/delete/$
/plugins/example-plugin/^models/all-names/$
/plugins/example-plugin/^models/(?P<pk>[^/.]+)/$
/plugins/example-plugin/^models/(?P<pk>[^/.]+)/delete/$
/plugins/example-plugin/^models/(?P<pk>[^/.]+)/edit/$
/plugins/example-plugin/^models/(?P<pk>[^/.]+)/changelog/$
/plugins/example-plugin/^models/(?P<pk>[^/.]+)/notes/$
/plugins/example-plugin/^other-models/$
/plugins/example-plugin/^other-models/add/$
/plugins/example-plugin/^other-models/edit/$
/plugins/example-plugin/^other-models/delete/$
/plugins/example-plugin/^other-models/(?P<pk>[^/.]+)/$
/plugins/example-plugin/^other-models/(?P<pk>[^/.]+)/delete/$
/plugins/example-plugin/^other-models/(?P<pk>[^/.]+)/edit/$
/plugins/example-plugin/^other-models/(?P<pk>[^/.]+)/changelog/$
/plugins/example-plugin/^other-models/(?P<pk>[^/.]+)/notes/$
Source code in nautobot/utilities/utils.py
def get_url_patterns(urlconf=None, patterns_list=None, base_path="/"):
    """
    Recursively yield a list of registered URL patterns.

    Args:
        urlconf (URLConf): Python module such as `nautobot.core.urls`.
            Default if unspecified is the value of `settings.ROOT_URLCONF`, i.e. the `nautobot.core.urls` module.
        patterns_list (list): Used in recursion. Generally can be omitted on initial call.
            Default if unspecified is the `url_patterns` attribute of the given `urlconf` module.
        base_path (str): String to prepend to all URL patterns yielded.
            Default if unspecified is the string `"/"`.

    Yields:
        (str): Each URL pattern defined in the given urlconf and its descendants

    Examples:
        >>> generator = get_url_patterns()
        >>> next(generator)
        '/'
        >>> next(generator)
        '/search/'
        >>> next(generator)
        '/login/'
        >>> next(generator)
        '/logout/'
        >>> next(generator)
        '/circuits/circuits/<uuid:pk>/terminations/swap/'

        >>> import example_plugin.urls as example_urls
        >>> for url_pattern in get_url_patterns(example_urls, base_path="/plugins/example-plugin/"):
        ...     print(url_pattern)
        ...
        /plugins/example-plugin/
        /plugins/example-plugin/config/
        /plugins/example-plugin/models/<uuid:pk>/dynamic-groups/
        /plugins/example-plugin/other-models/<uuid:pk>/dynamic-groups/
        /plugins/example-plugin/docs/
        /plugins/example-plugin/circuits/<uuid:pk>/example-plugin-tab/
        /plugins/example-plugin/devices/<uuid:pk>/example-plugin-tab-1/
        /plugins/example-plugin/devices/<uuid:pk>/example-plugin-tab-2/
        /plugins/example-plugin/override-target/
        /plugins/example-plugin/^models/$
        /plugins/example-plugin/^models/add/$
        /plugins/example-plugin/^models/import/$
        /plugins/example-plugin/^models/edit/$
        /plugins/example-plugin/^models/delete/$
        /plugins/example-plugin/^models/all-names/$
        /plugins/example-plugin/^models/(?P<pk>[^/.]+)/$
        /plugins/example-plugin/^models/(?P<pk>[^/.]+)/delete/$
        /plugins/example-plugin/^models/(?P<pk>[^/.]+)/edit/$
        /plugins/example-plugin/^models/(?P<pk>[^/.]+)/changelog/$
        /plugins/example-plugin/^models/(?P<pk>[^/.]+)/notes/$
        /plugins/example-plugin/^other-models/$
        /plugins/example-plugin/^other-models/add/$
        /plugins/example-plugin/^other-models/edit/$
        /plugins/example-plugin/^other-models/delete/$
        /plugins/example-plugin/^other-models/(?P<pk>[^/.]+)/$
        /plugins/example-plugin/^other-models/(?P<pk>[^/.]+)/delete/$
        /plugins/example-plugin/^other-models/(?P<pk>[^/.]+)/edit/$
        /plugins/example-plugin/^other-models/(?P<pk>[^/.]+)/changelog/$
        /plugins/example-plugin/^other-models/(?P<pk>[^/.]+)/notes/$
    """
    if urlconf is None:
        urlconf = settings.ROOT_URLCONF
    if patterns_list is None:
        patterns_list = get_resolver(urlconf).url_patterns

    for item in patterns_list:
        if isinstance(item, URLPattern):
            yield base_path + str(item.pattern)
        elif isinstance(item, URLResolver):
            # Recurse!
            yield from get_url_patterns(urlconf, item.url_patterns, base_path + str(item.pattern))