Opened 10 days ago

Closed 9 days ago

Last modified 9 hours ago

#35985 closed Cleanup/optimization (wontfix)

FORCE_SCRIPT_NAME ignored when running reverse() on non-main thread — at Version 2

Reported by: Pēteris Caune Owned by:
Component: Core (URLs) Version: dev
Severity: Normal Keywords:
Cc: Florian Apolloner Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Natalia Bidart)

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.

Change History (2)

comment:1 by Natalia Bidart, 9 days ago

Cc: Florian Apolloner added
Resolution: wontfix
Status: newclosed
Type: BugCleanup/optimization
Version: 5.1dev

Hello Pēteris Caune, thank you for taking the time to create this report. I have read your description carefully and I yes, I agree, the fact that _prefixes is local to the thread means that spawned threads will not share its contents. Also the function set_script_prefix has this docstring:

Set the script prefix for the current thread.

For a workaround, Django will set the prefix when setup is called, perhaps the best option for your management command is to call setup in each thread? Feels cleaner and more correct.

Regarding your comment for change django.urls implementation so that threads do share the script prefix storage, in my opinion this is beyond to what the main goal of Django is. As shown above, this is simple to add/solve to your code base, and to me this is a very specific need arising from a niche use case. I don't think this applies to the broader ecosystem, and Django is a framework designed to offer robust and accurate solutions for common scenarios.

Given the above, I'll close the ticket accordingly, but if you disagree, you can consider starting a new conversation on the Django Forum, where you'll reach a wider audience and likely get extra feedback.

comment:2 by Natalia Bidart, 9 days ago

Description: modified (diff)
Summary: SCRIPT_NAME / FORCE_SCRIPT_NAME ignored when running reverse() on non-main threadFORCE_SCRIPT_NAME ignored when running reverse() on non-main thread
Note: See TracTickets for help on using tickets.
Back to Top