#35985: FORCE_SCRIPT_NAME ignored when running reverse() on non-main thread
-------------------------------------+-------------------------------------
Reporter: Pēteris Caune | Owner: (none)
Type: | Status: closed
Cleanup/optimization |
Component: Core (URLs) | Version: dev
Severity: Normal | Resolution: wontfix
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Natalia Bidart):
* summary:
SCRIPT_NAME / FORCE_SCRIPT_NAME ignored when running reverse() on non-
main thread
=> FORCE_SCRIPT_NAME ignored when running reverse() on non-main thread
Old description:
> I've configured my Django project to run on a subpath (under
> `
example.org/some_prefix` instead of `
example.org`).
>
> The project has a management command which generates URLs using
> `django.urls.reverse()`.
>
> Since the management command cannot read SCRIPT_NAME from WSGI
> parameters, the project has `FORCE_SCRIPT_NAME = "/some_prefix"` in
> settings.py.
>
> The management command generates URLs that include the prefix as expected
> if the code runs on main thread. But if the management command spawns a
> thread, the code running on thread **generates URLs without the prefix**.
>
> I'm not sure but I think this is related to `hc.urls.base._prefix` being
> a `Local` object. I'm guessing it, as the name suggests, does not share
> data between threads. Even though `set_script_prefix` is called on main
> thread, the other threads do not see it.
>
> A simple workaround is for the user to call `set_script_prefix` by
> themselves:
>
> {{{
> from django.conf import settings
> from django.urls import set_script_prefix
>
> def this_will_be_run_on_thread():
> if settings.FORCE_SCRIPT_NAME:
> set_script_prefix(settings.FORCE_SCRIPT_NAME)
> # do work here
> }}}
>
> But perhaps there's something Django could do here as well:
>
> * perhaps, change django.urls implementation so that threads do share the
> script prefix storage?
> * if there are disadvantages to that, mention this gotcha in the
> documentation
>
> I'm happy to provide a dummy project demonstrating the issue if that
> would be helpful.
New description:
I've configured my Django project to run on a subpath (under
`
example.org/some_prefix` instead of `
example.org`).
The project has a management command which generates URLs using
`django.urls.reverse()`.
Since the management command cannot read SCRIPT_NAME from WSGI parameters,
the project has `FORCE_SCRIPT_NAME = "/some_prefix"` in settings.py.
The management command generates URLs that include the prefix as expected
if the code runs on main thread. But if the management command spawns a
thread, the code running on thread **generates URLs without the prefix**.
I'm not sure but I think this is related to `django.urls.base._prefixes`
being a `Local` object. I'm guessing it, as the name suggests, does not
share data between threads. Even though `set_script_prefix` is called on
main thread, the other threads do not see it.
A simple workaround is for the user to call `set_script_prefix` by
themselves:
{{{
from django.conf import settings
from django.urls import set_script_prefix
def this_will_be_run_on_thread():
if settings.FORCE_SCRIPT_NAME:
set_script_prefix(settings.FORCE_SCRIPT_NAME)
# do work here
}}}
But perhaps there's something Django could do here as well:
* perhaps, change django.urls implementation so that threads do share the
script prefix storage?
* if there are disadvantages to that, mention this gotcha in the
documentation
I'm happy to provide a dummy project demonstrating the issue if that would
be helpful.
--
--
Ticket URL: <
https://code.djangoproject.com/ticket/35985#comment:2>
Django <
https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.