#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
-------------------------------------+-------------------------------------
Comment (by Florian Apolloner):
Hi Pēteris, nice to see you here again :) I will go out on a limb and say
that I think `FORCE_SCRIPT_NAME` and everything it interacts with is
broken beyond repair. I had similar problems in a project of mine and I
opted for the following:
{{{#!python
prefix = f"{settings.BASE_URL.lstrip('/')}/" if settings.BASE_URL else ""
urlpatterns = [
path(f"{prefix}api/v1/", api.urls),
path(f"{prefix}", include(oversight_urlpatterns)),
path(f"{prefix}accounts/", include("allauth.urls")),
]
}}}
So essentially I introduced a `BASE_URL` which I prepend so `reverse`
works fine. Given how your WSGI integration works you might run into
problems though with the WSGI environment. That is usually fixable (in my
case it was not a problem since I am proxying from traefik to gunicorn --
if you are using something more embedded like mod_wsgi/uwsgi then you
might need some adjustments). All in all my approach has additional
benefits: I can reuse the `BASE_URL` for `MEDIA_URL`/`STATIC_URL` as well
without having to worry that it breaks easily like it does with
`FORCE_SCRIPT_NAME` and it will also work with threads ;) If you have more
questions about that approach feel free to contact me out of band or
mention me in a
healthchecks.io (I assume it is for said project?)
issue/discussion.
Like Natalia I am kinda hesitant to document `set_script_prefix`. In an
ideal world I'd love Django to adopt a `BASE_URL` (which actually is the
whole URL and not just the path like in my project) because then Django
finally knows where it is mounted and we could extend url resolving to
handle subdomains etc as well. Also most of the `ALLOWED_HOSTS` magic
becomes moot if you just generate URLs etc using `BASE_URL` without having
to rely on the host header.
Regarding running `django.setup()` in multiple threads: I don't think that
this is something we support or test -- so I would stay far away from it.
--
Ticket URL: <
https://code.djangoproject.com/ticket/35985#comment:5>