Re: [Django] #35985: FORCE_SCRIPT_NAME ignored when running reverse() on non-main thread (was: SCRIPT_NAME / FORCE_SCRIPT_NAME ignored when running reverse() on non-main thread)

2 views
Skip to first unread message

Django

unread,
Dec 9, 2024, 9:21:47 AM12/9/24
to django-...@googlegroups.com
#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.
Reply all
Reply to author
Forward
0 new messages