#34997 closed Bug (invalid)

The name argument is ignored when creating url path using the include() function.

Reported by: Sangwoon Yun Owned by: Sangwoon Yun
Component: Core (URLs) Version: 4.2
Severity: Normal Keywords: ulrs, path
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Let me briefly show you an example code that is ignored.

Our situation is when we use rest_framework.

from django.urls import path, include
from rest_framework.routers import DefaultRouter

from testapp.views import TestView

app_name = 'test_namespace'

test_router = DefaultRouter(trailing_slash=False)
test_router.register('test', TestView)

urlpatterns = [
    path('', include(test_router.urls), name='test')
]

If we use test as the name argument for the path() function in urls.py as above, we expect to get a url /test return when we use the reverse() function.
However, the name provision is ignored and returns the model name-based url_name, which is the default by the register() method in the code above.
The results of confirming the above causes through reverse engineering are as follows.
The code below is from lines 61 to 91 of django.urls' conf.py file.

def _path(route, view, kwargs=None, name=None, Pattern=None):
    from django.views import View

    if kwargs is not None and not isinstance(kwargs, dict):
        raise TypeError(
            f"kwargs argument must be a dict, but got {kwargs.__class__.__name__}."
        )
    if isinstance(view, (list, tuple)):
        # For include(...) processing.
        pattern = Pattern(route, is_endpoint=False)
        urlconf_module, app_name, namespace = view
        return URLResolver(
            pattern,
            urlconf_module,
            kwargs,
            app_name=app_name,
            namespace=namespace,
        )
    elif callable(view):
        pattern = Pattern(route, name=name, is_endpoint=True)
        return URLPattern(pattern, view, kwargs, name)
    elif isinstance(view, View):
        view_cls_name = view.__class__.__name__
        raise TypeError(
            f"view must be a callable, pass {view_cls_name}.as_view(), not "
            f"{view_cls_name}()."
        )
    else:
        raise TypeError(
            "view must be a callable or a list/tuple in the case of include()."
        )

if isinstance(view, (list, tuple)) statement is a case when using the include() function.
If you look at the code, URLResolver's app_name argument simply uses the app_name from the view argument.
It will ignore the name argument that can be used when invoking the path() function without any logic.
Although my example code is DRF and not pure django, I think we need a procedure to check the name argument of the path() function declared at the end.

This code can be resolved with a single line of modification.
We can modify code on line 76 as below:

from

app_name=app_name,

to

app_name=name if name else app_name,

Change History (2)

comment:1 by Sangwoon Yun, 10 months ago

Owner: changed from nobody to Sangwoon Yun
Status: newassigned

comment:2 by Mariusz Felisiak, 10 months ago

Resolution: invalid
Status: assignedclosed

Thanks for this ticket, however I'm not sure how name could work for path() in include(). name and app_name are two different things, if you want to define app_name when calling include() you should pass a tuple, check out docs.

If you're having trouble understanding how it works, see TicketClosingReasons/UseSupportChannels for ways to get help.

Note: See TracTickets for help on using tickets.
Back to Top