Opened 2 years ago
Closed 2 years ago
#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 , 2 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
comment:2 by , 2 years ago
| Resolution: | → invalid |
|---|---|
| Status: | assigned → closed |
Thanks for this ticket, however I'm not sure how
namecould work forpath()ininclude().nameandapp_nameare two different things, if you want to defineapp_namewhen callinginclude()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.